Docker Networking Basics

Container networking is the most confusing aspect of Docker—until you understand that "each container has its own localhost."

1. What You'll Learn


2. A Developer’s True Story

(1) Issue: Cannot connect to localhost between containers

Alice's web application and database are running in two separate containers, and the web container, using localhost:5432, cannot connect to the database. She was puzzled for two hours: "The database is clearly listening on port 5432, so why can't it connect?"

(2) Solutions for Container Network Isolation

Bob said, "Each container has its own localhost. The localhost for the web container is the web application itself, not the database. You need to use the container name or custom network communication."

BASH
# Create a custom network for inter-container communication
docker network create app-net

# Start containers on the same network
docker run -d --name db --network app-net -e POSTGRES_PASSWORD=secret postgres:15
docker run -d --name web --network app-net -p 8080:5000 myapp

# Web connects to db:5432 (not localhost:5432)

(3) Benefit: Network issue resolved in 2 hours → 5 minutes

Once she understood the container networking model, Alice was able to resolve her networking issue in 5 minutes—down from 2 hours of troubleshooting.


3. Four Docker Networking Modes

(1) Overview of Patterns

100%
graph TB
    subgraph Bridge["Bridge Mode (default)"]
        B1["Container A<br/>172.17.0.2"] --- B2["docker0 bridge<br/>172.17.0.1"]
        B2 --- B3["Container B<br/>172.17.0.3"]
        B2 --- B4["Host eth0<br/>via NAT"]
    end
    subgraph Host["Host Mode"]
        H1["Container"] --- H2["Host Network Stack<br/>Shares all ports"]
    end
    subgraph None["None Mode"]
        N1["Container<br/>Loopback only"]
    end
    subgraph Overlay["Overlay Mode"]
        O1["Container A<br/>Host 1"] -.- O2["Container B<br/>Host 2"]
    end

(2) Comparison of the Four Modes

Dimension Bridge Host None Overlay
Isolation Dedicated Network Stack Shared Host Network Fully Isolated Cross-Host Virtual Network
Port Forwarding Requires -p Not required Not available Built-in routing
Performance Medium (NAT overhead) High (direct access) - Medium (VXLAN encapsulation)
DNS Resolution Custom bridge only None (shared hosting) None ✅ Built-in
Cross-host
Use Cases Single-machine, multi-container High-performance networking Security isolation/debugging Docker Swarm clusters

4. A Detailed Explanation of the Bridge Network

(1) Default bridge vs. custom bridge

Dimension Default bridge Custom bridge
DNS Resolution ❌ IP addresses only ✅ Communicate using container names
Container Isolation All containers on the same network Isolated by network group
Recommendation Level ⭐ (Compatible with older versions) ⭐⭐⭐ (Recommended)
Creation Method Automatically created by Docker docker network create

▶ Example: Creating a Custom Bridge Network (Difficulty: ⭐)

BASH
# Create a custom bridge network
docker network create --driver bridge app-net

# Verify
docker network ls | grep app-net
docker network inspect app-net

▶ Example: DNS Resolution Between Containers (Difficulty: ⭐⭐)

BASH
# Start two containers on the same custom network
docker run -d --name db --network app-net \
  -e POSTGRES_PASSWORD=secret postgres:15-alpine
docker run -d --name api --network app-net \
  nginx:alpine

# DNS resolution: api can reach db by name
docker exec api ping -c 2 db
💻 Output:

TEXT
PING db (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.100 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.050 ms
📌 Key Point: The custom bridge network automatically registers DNS records for each container. The container name serves as the hostname—db resolves to the IP address of the database container. This is why fastcgi_pass lemp-php:9000 works in the Phase 1 LEMP project.

▶ Example: Network Isolation Verification (Difficulty: ⭐⭐)

BASH
# Create two separate networks
docker network create frontend-net
docker network create backend-net

# Frontend container
docker run -d --name web --network frontend-net nginx:alpine

# Backend container
docker run -d --name api --network backend-net nginx:alpine

# web CANNOT reach api (different networks)
docker exec web ping -c 2 -W 2 api
# Output: ping: bad address 'api'

# Connect web to backend-net (now it can reach api)
docker network connect backend-net web
docker exec web ping -c 2 api
# Output: PING api (172.19.0.2): 64 bytes

5. Host Network Mode

▶ Example: Running a Container in Host Mode (Difficulty: ⭐⭐)

BASH
# Run with host network (shares host's network stack)
docker run -d --name host-nginx --network host nginx:alpine

# No port mapping needed - nginx directly listens on host's port 80
curl http://localhost:80
⚠️ Note: In Host mode, containers use the host’s ports directly and do not require -p mapping. However, there is a high risk of port conflicts—if port 80 on the host is already in use, the container will fail to start. Use with caution in production environments.


6. How Port Forwarding Works

(1) Three Ways to Expose Ports

Method Syntax Description
-p host:container -p 8080:80 Specified mapping
-P -P Randomly mapped to ports declared in EXPOSE
--network host --network host No port mapping required (shared host network)

▶ Example: Use docker network inspect to view network details (Difficulty: ⭐⭐)

BASH
# Inspect network configuration
docker network inspect app-net
💻 Output (excerpt):

TEXT
[
  {
    "Name": "app-net",
    "Driver": "bridge",
    "IPAM": {
      "Config": [{"Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1"}]
    },
    "Containers": {
      "a1b2c3d4...": {"Name": "db", "IPv4Address": "172.18.0.2"},
      "e5f6a7b8...": {"Name": "api", "IPv4Address": "172.18.0.3"}
    }
  }
]

7. Complete Example: Three-Layer Network Architecture

BASH
# ============================================
# Complete walkthrough: Three-tier network architecture
# Frontend / Backend / Database isolation
# ============================================

# 1. Create three networks
docker network create frontend-net
docker network create backend-net
docker network create db-net

# 2. Start database (only on db-net)
docker run -d --name db \
  --network db-net \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=myapp \
  postgres:15-alpine

# 3. Start API server (backend-net + db-net)
docker run -d --name api \
  --network backend-net \
  -e DATABASE_URL="postgresql://postgres:secret@db:5432/myapp" \
  myapp-api:1.0

# Connect API to db-net so it can reach the database
docker network connect db-net api

# 4. Start Nginx (frontend-net + backend-net)
docker run -d --name web \
  --network frontend-net \
  -p 8080:80 \
  -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf \
  nginx:1.25-alpine

# Connect Nginx to backend-net so it can reach the API
docker network connect backend-net web

# 5. Verify connectivity
docker exec web ping -c 1 api     # web → api ✅
docker exec api ping -c 1 db      # api → db ✅
docker exec web ping -c 1 -W 1 db # web → db ❌ (not on db-net)

# 6. Clean up
docker stop web api db
docker rm web api db
docker network rm frontend-net backend-net db-net

❓ FAQ

Q Can two containers communicate if they are not on the same network?
A By default, no. Each network is an independent, isolated domain. To allow Container A to access Container C in Network B, you need to use docker network connect to add A to Network B. A container can belong to multiple networks at the same time.
Q What are the risks of using host network mode?
A There are two main risks: ① Port conflicts—containers listen directly on host ports, so they will fail to start if those ports are already in use by other services; ② Security—containers can access all of the host’s network interfaces, including internal services on localhost. Use host mode only when you need maximum network performance.
Q Does the container's IP address change?
A Yes. The IP address may change after the container restarts (especially for non-user-defined subnets). This is why you should communicate using container names (via DNS resolution) rather than IP addresses. For custom bridge networks, DNS automatically maintains the mapping from container names to IP addresses.
Q How can I restrict network access for containers?
A There are three ways: ① Use multiple networks for isolation (recommended)—the database is only on db-net, so the frontend cannot access it directly; ② Use iptables rules (advanced); ③ --icc=false Disable inter-container communication on the default bridge (not recommended; using a custom network is better).
Q How do containers communicate across hosts?
A Single-host Docker cannot communicate directly across hosts. Solutions: ① Overlay networking (requires Docker Swarm or manual configuration of etcd); ② Port mapping + host IP; ③ Third-party networking plugins (Weave/Calico). Docker Swarm’s Overlay networking is the simplest solution for cross-host communication (Phase 4, Lesson 20).

📖 Summary


📝 Exercises

  1. Basic Exercise (Difficulty ⭐): Create a custom bridge network, start two Nginx containers, and verify that the container names resolve via DNS (docker exec A ping B).
  2. Advanced Problem (Difficulty ⭐⭐): Create two separate networks, place one container in each, and verify that containers in different networks cannot ping each other. Then use docker network connect to connect them.
  3. Challenge (Difficulty: ⭐⭐⭐): Use docker network inspect to view the IPAM configuration and container list for a custom network, and understand Docker’s internal network routing mechanism.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏