$docker.recipes
·12 min read·Updated November 2025

Docker Networking Explained: Bridge, Host, and Overlay Networks

A clear explanation of Docker's networking modes with practical examples showing when to use each one in your Docker Compose configurations.

dockernetworkingbridgedocker-compose

01Docker Networking Doesn't Have to Be Confusing

Docker networking is one of those topics that seems complex until it clicks. I struggled with it for months — containers that couldn't reach each other, port conflicts, services visible when they shouldn't be — until I understood the three networking modes and when to use each one. The good news: for Docker Compose deployments, you only need to understand two concepts well (bridge networks and the default compose network), and one concept at a high level (overlay networks for multi-host setups). This guide covers all three with practical examples from real deployments.

02The Default Compose Network

When you run docker compose up, Compose automatically creates a bridge network named {project}_default and attaches all services to it. Services can reach each other by their service name as a hostname. This is the most common networking setup, and it works perfectly for most applications:
[docker-compose.yml]
1# All services share the default network
2services:
3 app:
4 image: myapp:latest
5 environment:
6 # "db" resolves to the database container's IP
7 - DATABASE_URL=postgres://user:pass@db:5432/myapp
8
9 db:
10 image: postgres:16-alpine
11
12 redis:
13 image: redis:7-alpine
14
15# No network configuration needed!
16# app can reach db at "db:5432"
17# app can reach redis at "redis:6379"

Service names are DNS names within the network. Use the service name (not container_name) when configuring connections between services. This works even if you haven't set a container_name.

03Custom Bridge Networks for Isolation

The default network connects everything, which violates the principle of least privilege. Custom networks let you control which services can communicate:
[docker-compose.yml]
1services:
2 traefik:
3 image: traefik:v3.1
4 networks:
5 - frontend # Can reach web apps
6
7 app:
8 image: myapp:latest
9 networks:
10 - frontend # Reachable by Traefik
11 - backend # Can reach database
12
13 db:
14 image: postgres:16-alpine
15 networks:
16 - backend # Only reachable by app
17
18 redis:
19 image: redis:7-alpine
20 networks:
21 - backend
22
23networks:
24 frontend: # Public-facing services
25 backend:
26 internal: true # No external access possible

04Host Networking: When You Need Raw Performance

Host networking removes the network isolation between the container and the host. The container shares the host's network stack directly, with no NAT overhead. Use cases: Network monitoring tools (like cAdvisor, node-exporter) that need to see host network interfaces. High-performance applications where NAT overhead matters (rare). Services that need to bind to specific host interfaces. Limitations: No port mapping (the container uses host ports directly), so port conflicts are possible. No network isolation from the host. Not available on Docker Desktop for Mac/Windows.
[docker-compose.yml]
1services:
2 # Node exporter needs host networking to see
3 # real network interface stats
4 node-exporter:
5 image: prom/node-exporter:latest
6 network_mode: host
7 pid: host
8 volumes:
9 - /proc:/host/proc:ro
10 - /sys:/host/sys:ro

Host networking bypasses Docker's network isolation. Only use it when you specifically need host-level network access. For most services, bridge networking is safer and sufficient.

05Connecting Services Across Compose Files

A common question: how do you connect services defined in different docker-compose.yml files? The answer is external networks: Create a shared network once with docker network create proxy, then reference it in both compose files with external: true. This is how reverse proxies like Traefik connect to application containers defined in separate compose projects. This pattern is the foundation of a well-organized Docker home lab. Each service has its own directory and compose file, connected to shared networks as needed. Browse our web-servers category for Traefik and Caddy configurations that demonstrate this pattern.
[docker-compose.yml]
1# First: create shared network
2# docker network create proxy
3
4# traefik/docker-compose.yml
5services:
6 traefik:
7 networks:
8 - proxy
9networks:
10 proxy:
11 external: true
12
13# nextcloud/docker-compose.yml
14services:
15 nextcloud:
16 networks:
17 - proxy # Shared with Traefik
18 - internal # Private to this stack
19networks:
20 proxy:
21 external: true
22 internal:

About the Author

Frank Pegasus

DevOps engineer and self-hosting enthusiast with over a decade of experience running containerized workloads in production. Creator of docker.recipes.