Bridge Network
The default Docker network driver that creates an isolated virtual network on the host, connecting containers via a Linux bridge device. User-defined bridge networks add automatic DNS resolution by container name.
Bridge Network — The Default Way Docker Containers Communicate
What Is a Bridge Network in Simple Terms?
A bridge network is Docker's default way of connecting containers to each other and to the outside world. When you run docker run nginx without specifying a network, Docker automatically connects that container to the bridge network. The container gets a private IP address, and Docker sets up routing rules on the host so the container can reach the internet and you can publish ports to access it.
The name comes from the Linux networking concept — Docker creates a virtual network bridge device called docker0 on the host, and every container on the bridge network connects to it like a switch.
+------------------------------------------+| Linux Host || || docker0 bridge (172.17.0.1) || | | | || v v v || +--------+ +--------+ +--------+ || |nginx | |api | |db | || |.0.2 | |.0.3 | |.0.4 | || +--------+ +--------+ +--------+ || || iptables NAT rules: || containers -> internet (masquerade) || -p 8080:80 -> DNAT to container IP |+------------------------------------------+Default Bridge vs User-Defined Bridge
There are two types of bridge network and they behave very differently:
+------------------------------------------+| Default Bridge (docker0) || || Created automatically by Docker || All containers join this by default || || NO DNS — containers can only reach || each other by IP address || IP addresses change on restart || NOT suitable for multi-container apps |+------------------------------------------+ +------------------------------------------+| User-Defined Bridge || || Created with: docker network create || Containers join with --network flag || || HAS DNS — containers resolve each || other by container name || Name-based addressing is stable || CORRECT choice for real applications |+------------------------------------------+How Linux Bridge Networking Works
# When Docker creates a bridge network, it creates a Linux bridge deviceip link show# docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500# br-a84f9c2b: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500# ^ user-defined bridge network # Each container gets a veth pair (virtual ethernet cable)# One end inside the container (eth0)# Other end on the host connected to the bridgeip link show | grep veth# veth3a2b1c0@if4: <- connected to container eth0 # iptables handles routingsudo iptables -t nat -L POSTROUTING# MASQUERADE all -- 172.17.0.0/16 -> internet (outbound NAT)# MASQUERADE all -- 172.18.0.0/16 -> internet (user-defined network)Working With Bridge Networks
# Default bridge — containers join automaticallydocker run -d --name web nginxdocker run -d --name api node:20-alpine sleep 3600 # Cannot reach by name on default bridgedocker exec api ping web# ping: bad address 'web' — NO DNS on default bridge # Must use IP — but IP changes on restartdocker inspect web --format '{{.NetworkSettings.IPAddress}}'# 172.17.0.2docker exec api ping 172.17.0.2# works, but fragile # Create a user-defined bridgedocker network create payment-network # Run containers on user-defined bridgedocker run -d --name payment-api \ --network payment-network \ registry.razorpay.in/payment-api:v3.1.0 docker run -d --name postgres \ --network payment-network \ postgres:15 -e POSTGRES_PASSWORD=secret # Now DNS works — containers find each other by namedocker exec payment-api ping postgres# PING postgres (172.18.0.3) — success # List all networksdocker network ls# NETWORK ID NAME DRIVER# a84f9c2b1d bridge bridge <- default# b72c8a9f4e payment-network bridge <- user-defined # Inspect a networkdocker network inspect payment-network# Shows subnet, gateway, connected containers and their IPs # Connect an existing container to another networkdocker network connect monitoring-network payment-api# payment-api is now on both payment-network and monitoring-network # Remove a network (all containers must be disconnected first)docker network rm payment-network # Remove all unused networksdocker network pruneBridge Networks in Docker Compose
Docker Compose automatically creates a user-defined bridge network for each project:
# docker-compose.ymlversion: "3.8"services: api: image: payment-api:latest postgres: image: postgres:15# Compose creates: projectname_default bridge network# api can reach postgres by name: postgres# postgres can reach api by name: api# No extra network config needed for basic use# See the auto-created networkdocker network ls | grep projectname# projectname_default bridge localTroubleshooting Bridge Network Issues
| Problem | Cause | Fix |
|---|---|---|
| Container name not resolving | On default bridge (no DNS) | Create user-defined network |
| Cannot reach internet from container | iptables FORWARD rules missing | Restart Docker: systemctl restart docker |
| Port binding fails | Another process using host port | Check `ss -tulpn |
| Two containers cannot communicate | On different networks | docker network connect network-name container |
| IP address keeps changing | Using default bridge by name | Use user-defined bridge — names are stable |
TipAlways create a user-defined bridge network for any multi-container application. The one-line command
docker network create app-networktakes 2 seconds and gives you DNS, better isolation, and stable container name resolution. The default bridge network is only suitable for running a single standalone container.
RememberThe default bridge network
docker0has no DNS — containers can only find each other by IP address which changes on every restart. User-defined bridge networks automatically provide DNS resolution by container name. This single difference is the most important thing to understand about Docker networking.
Common MistakeTrying to use container names in application config when containers are on the default bridge network.
DB_HOST=postgresin your environment variables will fail withname not resolvedon the default bridge. Either create a user-defined network or use Docker Compose which creates one automatically.
SecurityContainers on the same bridge network can communicate with each other on any port without restriction. If you need to restrict which containers can talk to which, use Docker Network Policies or move services that should not communicate onto separate networks.
Frequently Asked Questions
Why does Docker recommend user-defined bridge networks over the default one?
Containers on the default bridge network can only reach each other by IP address — there's no built-in DNS resolution by container name, so linking services requires either hardcoded IPs (which change on restart) or the deprecated `--link` flag. A user-defined bridge network runs an embedded DNS server that resolves container names to their current IP automatically, which is why `docker-compose` creates a dedicated bridge network per project by default rather than using the default one.
What's a common networking mistake with bridge networks in production-like setups?
Assuming containers on a bridge network are as isolated from the host as they are from each other. Published ports (`-p 8080:80`) punch through the bridge's iptables rules to the host's network interface, and by default that binds to all host interfaces (`0.0.0.0`), not just localhost — exposing the container to anything that can reach the host's network, not just other local processes. Binding to `127.0.0.1:8080:80` instead is the fix when the port should only be reachable locally.