Communication Models Between Containers
Containers don’t just run within their own networks—they need to discover and communicate with one another. Understanding how containers communicate with each other is the foundation for building a microservices architecture.
1. What You'll Learn
- Three Ways for Containers to Communicate with Each Other
- Advanced Uses of Container Aliases and DNS
- Methods for Troubleshooting Network Issues
- Port Exposure Policy
- Security Group Isolation Design
2. A True Story from a Microservices Developer
(1) Pain Point: The three microservices are not connected to each other
Charlie deployed three microservice containers: API Gateway, User Service, and Order Service. API Gateway could access the User Service, but the requests always timed out. After two hours of troubleshooting, he discovered that API Gateway had exposed a port but the firewall was not enabled, the User Service was using the wrong container name, and the Order Service was on a different network.
(2) Solutions for Systematic Network Scanning
Bob taught him a network troubleshooting process: container name → DNS → network → port.
# Step 1: Verify DNS resolution
docker exec api nslookup user-service
# Step 2: Test network connectivity
docker exec api ping -c 2 user-service
# Step 3: Test port connectivity
docker exec api nc -zv user-service 8080
(3) Benefits: Network troubleshooting time reduced from 2 hours to 10 minutes
With a systematic troubleshooting process in place, the time it took Charlie to troubleshoot network issues dropped from 2 hours to 10 minutes.
3. Three Methods of Inter-Container Communication
(1) Comparison of Methods
graph TB
subgraph Method1["① --link (Legacy, Deprecated)"]
L1["Container A"] -->|"env vars + /etc/hosts"| L2["Container B"]
end
subgraph Method2["② Custom Network + DNS (Recommended)"]
D1["Container A"] -->|"DNS auto-resolve"| D2["Container B"]
end
subgraph Method3["③ Exposed Port + Host IP"]
E1["Container A"] -->|"host:port"| E2["Container B<br/>(via host bridge)"]
end
| Method | Principle | DNS | Status | Recommendation |
|---|---|---|---|---|
--link |
Environment Variables + hosts Injection | ❌ | ❌ Obsolete | ⭐ |
| Custom Network DNS | Docker Built-in DNS | ✅ | ✅ Recommended | ⭐⭐⭐ |
| Host Port Forwarding | Container→Host→Container | ❌ | Available | ⭐⭐ |
4. --link (Deprecated)
▶ Example: Understanding how --link works (Difficulty: ⭐)
# Legacy link: B can reach A by hostname
docker run -d --name db postgres:15-alpine
docker run -d --name web --link db:database nginx:alpine
# web can use "database" as hostname (via /etc/hosts)
docker exec web cat /etc/hosts
--link has been deprecated and is used solely for historical reference. It only supports one-way connections (web→db, not db→web), and the hosts file is not updated when the IP address changes after the container restarts. Always use a custom network instead.**
5. A Detailed Guide to Custom Network DNS
(1) The DNS Resolution Process
graph LR
A["Container A<br/>ping db"] --> B["Docker DNS<br/>127.0.0.11"]
B -->|db → 172.18.0.2| C["Container B<br/>172.18.0.2"]
▶ Example: --network-alias to set an alias (Difficulty: ⭐⭐)
# Start container with network alias
docker run -d --name my-postgres \
--network app-net \
--network-alias=database \
--network-alias=db \
postgres:15-alpine
# Both names resolve to the same container
docker exec api ping -c 1 database # resolves to my-postgres
docker exec api ping -c 1 db # same IP
(1) Container Name vs. Network Alias
| Type | Definition | Scope | Priority |
|---|---|---|---|
--name |
Container Name | All Networks | High |
--network-alias |
Network Alias | Specify Network Only | Medium |
| Docker Compose service name | Service name | Compose network | High |
--network-alias allows the same container to have different names in different networks. For example, the database is named primary-db in backend-net and database in admin-net.
6. Port Exposure Policy
(1) --expose vs -p vs -P
| Parameter | Function | Externally Accessible | Use Cases |
|---|---|---|---|
--expose 3306 |
Port Declaration (Documentation) | ❌ Not Mapped | Inter-container Communication |
-p 3306:3306 |
Mapped to host | ✅ Accessible from outside | External service |
-P |
Randomly Map EXPOSE Ports | ✅ Random Ports | Development and Debugging |
▶ Example: Use docker port to view port mappings (Difficulty: ⭐)
# Check port mappings for a container
docker port web
# Output example
80/tcp -> 0.0.0.0:8080
7. Network Troubleshooting
(1) Troubleshooting Decision Trees
graph TB
START["Container A<br/>cannot reach Container B"] --> DNS{"DNS Analysis?"}
DNS -->|Failure| FIX1["The Same Custom Network?<br/>Using --name or --network-alias"]
DNS -->|Success| PING{"Ping Through?"}
PING -->|Failure| FIX2["On the Same Network?<br/>docker network connect"]
PING -->|Success| PORT{"Port Connect?<br/>nc -zv B port"]
PORT -->|Failure| FIX3["Port Exposure?<br/>B Is the correct port being listened to??"]
PORT -->|Success| APP{"Application Protocol?<br/>curl/wget Test"]
APP -->|Failure| FIX4["Check the app configuration<br/>Environment Variables/URL"]
APP -->|Success| OK["✅ Communication is working properly"]
▶ Example: Commands for troubleshooting container networking (Difficulty: ⭐⭐)
# Step 1: Check DNS resolution
docker exec api nslookup db
docker exec api getent hosts db
# Step 2: Test basic connectivity
docker exec api ping -c 2 db
# Step 3: Test specific port
docker exec api nc -zv db 5432
# or with wget
docker exec api wget -qO- http://api:8080/health
# Step 4: Check container's network interfaces
docker exec api ip addr
# Step 5: Check routing table
docker exec api ip route
▶ Example: docker network connect to dynamically join a network (Difficulty: ⭐⭐)
# Connect a running container to another network
docker network connect backend-net web
# Disconnect from a network
docker network disconnect frontend-net web
# Verify container's networks
docker inspect web --format='{{json .NetworkSettings.Networks}}' | python3 -m json.tool
8. Security Group Isolation Design
(1) Three-Layer Isolation Model
| Network Layer | Container | Accessible | External Port |
|---|---|---|---|
| Frontend Net | Nginx/CDN | Backend Net only | 80, 443 |
| Backend Net | API/Worker | DB Net only | None(Via Nginx Proxy) |
| DB Net | PostgreSQL/Redis | No external access | None |
9. Complete Example: Microservice Network Configuration and Troubleshooting
# ============================================
# Complete walkthrough: Microservice networking
# Covers: networks, aliases, isolation, debugging
# ============================================
# 1. Create isolated networks
docker network create frontend-net
docker network create backend-net
docker network create db-net
# 2. Start database (db-net only)
docker run -d --name postgres \
--network db-net \
--network-alias=database \
--network-alias=primary-db \
-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 \
--network-alias=api-server \
-e DATABASE_URL="postgresql://postgres:secret@primary-db:5432/myapp" \
myapp-api:1.0
docker network connect db-net api
# 4. Start Nginx (frontend-net + backend-net)
docker run -d --name nginx \
--network frontend-net \
--network-alias=gateway \
-p 8080:80 \
nginx:1.25-alpine
docker network connect backend-net nginx
# 5. Debug: verify connectivity
echo "=== DNS Resolution ==="
docker exec nginx nslookup api-server
docker exec api nslookup primary-db
echo "=== Port Connectivity ==="
docker exec nginx nc -zv api-server 5000
docker exec api nc -zv primary-db 5432
echo "=== Isolation Check ==="
docker exec nginx sh -c "timeout 2 nc -zv primary-db 5432 2>&1 || echo 'BLOCKED: nginx cannot reach db directly (expected)'"
# 6. Clean up
docker stop postgres api nginx
docker rm postgres api nginx
docker network rm frontend-net backend-net db-net
❓ FAQ
docker network connect.db-net, only the API is added to db-net, so Nginx cannot directly access the database.docker exec <container> nslookup <target> Check the resolution results.docker inspect <container> --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'. Or enter the container and run ip addr / hostname -I. But remember: the IP address may change, so use the container name instead of the IP address in production code.📖 Summary
- For communication between containers, we recommend using a custom network + DNS; deprecate --link
- Custom bridge network: Container names are automatically registered with DNS, and containers on the same network communicate by name
--network-aliasAssign aliases to containers; the same container can have different names on different networks- Port exposure:
--exposedocumented only,-pmapped to the host,-Prandomly mapped - Four-step network troubleshooting: DNS resolution → Ping → Port test → Application protocol test
- Three-tier architecture: Frontend → Backend → Database; the database is not exposed to the frontend network
📝 Exercises
- Basic Exercise (Difficulty: ⭐): Create two custom networks, start one container on each, and verify that DNS resolution for container names within the same network works properly.
- Advanced Exercise (Difficulty ⭐⭐): Verify that containers across networks cannot ping each other, then establish a connection using
docker network connect, and then disconnect. - Challenge Question (Difficulty: ⭐⭐⭐): Use
docker exec+nc/wgetto troubleshoot the root cause of one container being unable to access another container’s service. Describe the troubleshooting steps and draw a conclusion.



