Docker Networking
Bridge, host, and overlay networks; port mapping; container-to-container communication
Free tier: read the explanation here. Upgrade to Pro for Drills, Speed challenges & Mastery badges.
UpgradeKnowledge Debt detected
You can study this freely — but your score may plateau if these foundations have gaps. The Mastery badge requires them to be solid.
Explanation
Docker's networking model controls how containers communicate with each other and with the outside world.
Network drivers:
| Driver | Use case | |---|---| | bridge (default) | Containers on the same host communicate via a virtual switch | | host | Container shares the host's network stack (no port mapping needed) | | overlay | Multi-host networking for Docker Swarm / distributed clusters | | none | No networking — fully isolated container |
Default bridge network:
bash docker network ls # NETWORK ID NAME DRIVER SCOPE # abc123 bridge bridge local ← default docker run -d --name app1 nginx docker run -d --name app2 nginx # On the default bridge, containers can reach each other by IP, # but NOT by container name — use a user-defined bridge for DNS
User-defined bridge — enables name resolution:
bash docker network create mynet docker run -d --name db --network mynet postgres:16 docker run -d --name app --network mynet myapp # Inside app, you can now reach Postgres by name: # psql -h db -U postgres `` On user-defined bridges, Docker provides automatic DNS: containers resolve each other by name.
Port mapping (publish):
bash # -p host_port:container_port docker run -p 8080:80 nginx # host:8080 → container:80 docker run -p 127.0.0.1:8080:80 nginx # bind only to localhost docker run -P nginx # publish all EXPOSE'd ports to random host ports Without -p`, the container's ports are unreachable from the host — only accessible by other containers on the same Docker network.
Compose networking:
yaml services: api: networks: - frontend - backend db: networks: - backend # db is NOT on frontend — api is the gateway networks: frontend: backend: `` Compose creates one default network for all services. Custom networks let you segment traffic — e.g., the database is unreachable from the public-facing network.
Inspecting networks:
bash docker network inspect mynet # JSON with all containers and IPs docker inspect app | grep IPAddress # IP of a specific container
Host networking (Linux only):
bash docker run --network host nginx # nginx listens on host port 80 directly — no NAT, lowest latency # Not recommended for multi-container apps (port conflicts)
Examples
Segmented network: public + private tiers
Multi-network segmentation is the standard pattern for production: the database sits behind the API with no direct external access
# docker-compose.yml
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
networks:
- public # reachable from internet via port 80
api:
build: .
networks:
- public # nginx can proxy to api
- private # api can reach db
db:
image: postgres:16-alpine
networks:
- private # NOT exposed to public network
networks:
public:
private:
# Result:
# internet → nginx (public) → api (public+private) → db (private)
# db is never directly reachable from outsideCreating and using a user-defined network manually
User-defined bridges provide DNS-based discovery; the default bridge network only provides IP-based communication
# Create a named network
docker network create appnet
# Start containers on the same network
docker run -d --name postgres --network appnet -e POSTGRES_PASSWORD=secret postgres:16
docker run -d --name api --network appnet -p 8000:8000 myapp
# Inside the api container, connect to postgres by name:
# DATABASE_URL=postgresql://postgres:secret@postgres:5432/mydb
# "postgres" resolves because they're on the same user-defined bridge
# Check connectivity
docker exec api ping postgres # should resolve + respond
# Inspect the network to see all connected containers
docker network inspect appnetHow well did you understand this?