Docker: Docker Networking Basics
Last updated: 2026-08-26
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."
# 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: ⭐)
# 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: ⭐⭐)
# 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
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
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: ⭐⭐)
# 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: ⭐⭐)
# 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
-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: ⭐⭐)
# Inspect network configuration
docker network inspect app-net
[
{
"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
# ============================================
# 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
docker network connect to add A to Network B. A container can belong to multiple networks at the same time.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).📖 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.