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
- Differences Among the Four Network Modes
- Customize the bridge network and DNS
- Mechanisms for Communication Between Containers
- Network Isolation Policy
- How Port Forwarding Works
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
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
- Four network modes: Bridge (default/recommended for custom configurations), Host (high performance), None (isolated), Overlay (cross-host)
- The default bridge does not support DNS, while the custom bridge supports DNS resolution for container names—always use the custom bridge
- Each container has its own localhost; containers communicate with each other using container names rather than localhost
- Multi-network isolation implements a three-tier architecture: Frontend ↔ Backend ↔ Database
docker network connectAdding a Container to Multiple Networks- Port Mapping
-p host:containerExposes Container Services to the Outside World
📝 Exercises
- 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). - 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 connectto connect them. - Challenge (Difficulty: ⭐⭐⭐): Use
docker network inspectto view the IPAM configuration and container list for a custom network, and understand Docker’s internal network routing mechanism.



