Docker Networking – How Containers Talk to Each Other
Every container needs to communicate — with users, with databases, with other services. Docker has a built-in networking system that gives containers their own IP addresses, lets them talk to each other, and controls what is accessible from outside. This topic explains Docker networking through diagrams and practical examples.
The Default Network Setup
When you install Docker, it automatically creates three networks:
docker network ls NETWORK ID NAME DRIVER SCOPE a1b2c3d4e5f6 bridge bridge local b2c3d4e5f6g7 host host local c3d4e5f6g7h8 none null local
The Bridge Network — The Default
Every container you start without specifying a network joins the default bridge network automatically. Docker creates a virtual network switch inside your machine and assigns each container an IP address on the 172.17.0.0/16 range.
Default Bridge Network: Your Machine (host) ┌──────────────────────────────────────────────────┐ │ │ │ Docker Bridge Network: 172.17.0.0/16 │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ │ │ Container A Container B │ │ │ │ nginx mysql │ │ │ │ IP: 172.17.0.2 IP: 172.17.0.3 │ │ │ │ │ │ │ │ Container A can reach B via 172.17.0.3 │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ Your machine IP: 172.17.0.1 (gateway) │ └──────────────────────────────────────────────────┘
The limitation of the default bridge: containers can reach each other by IP address but NOT by name. If Container A wants to reach MySQL, it must know MySQL's IP address (172.17.0.3), which can change every time you restart the container.
Custom Bridge Networks — The Right Way
Create your own bridge network to get automatic DNS resolution. Containers on the same custom network can reach each other by container name — no IP addresses needed.
Create a custom network: docker network create my-app-network Run containers on this network: docker run -d --name web --network my-app-network nginx docker run -d --name db --network my-app-network mysql:8.0 Now "web" can reach "db" by name: Inside the web container: ping db → works! Inside the web container: mysql -h db → works!
Custom Bridge Network with DNS: ┌─────────────────────────────────────────────────┐ │ my-app-network │ │ │ │ Container "web" Container "db" │ │ nginx mysql │ │ 10.0.0.2 10.0.0.3 │ │ │ │ web can use: http://db:3306/ │ │ No need to know IP addresses │ │ Docker's built-in DNS resolves "db" → 10.0.0.3 │ └─────────────────────────────────────────────────┘
Port Mapping — Connecting Containers to the Outside World
By default, containers are isolated. External traffic cannot reach them. Port mapping creates a tunnel from your host machine into the container.
docker run -d -p 8080:80 nginx
Port Mapping:
Internet/Browser Your Machine Container
↓ ┌──────────┐ ┌────────┐
GET http:// │ │ │ │
yourserver.com:8080 ─────────→ │ :8080 │────────→ │ :80 │
│ │ │ nginx │
└──────────┘ └────────┘
Format: -p HOST_PORT:CONTAINER_PORT
Multiple port mappings on one container:
docker run -d -p 8080:80 -p 443:443 nginx
Bind to a specific host interface (limit who can reach the port):
docker run -d -p 127.0.0.1:8080:80 nginx
↑
Only localhost can reach this — not external traffic
Host Network Mode
In host network mode, the container shares your machine's network directly. There is no isolation — the container uses your machine's IP and ports as if it were a regular process.
docker run -d --network host nginx
nginx now listens on your machine's port 80 directly. No port mapping needed. This is faster but less isolated — only use it when performance is critical.
Network Commands Reference
List networks: docker network ls Create network: docker network create my-net Inspect network: docker network inspect my-net Connect container: docker network connect my-net web Disconnect container: docker network disconnect my-net web Remove network: docker network rm my-net Remove unused: docker network prune
Container-to-Container Communication Example
Goal: Python web app talks to Redis cache
docker network create app-net
docker run -d \
--name redis \
--network app-net \
redis:7
docker run -d \
--name webapp \
--network app-net \
-p 5000:5000 \
-e REDIS_HOST=redis \
my-flask-app
Inside webapp: redis.connect("redis", 6379) → works!
"redis" resolves to the Redis container's IP automatically
