| |

Docker 32 🐳 Default Bridge Network vs User-Defined Bridge Networks and DNS Resolution

Two containers on the same host cannot talk to each other by name unless they are on a user-defined network. The default bridge network, the one Docker creates automatically at installation, does not provide DNS resolution between containers. This is not a bug; it is a deliberate limitation, kept for backward compatibility with the legacy --link mechanism . The user-defined bridge network solves the problem: Docker embeds a DNS server at 127.0.0.11, and every container on the network can resolve every other container by its name .

Key point: The default bridge network does not resolve container names. A user-defined bridge network does. The embedded DNS server at 127.0.0.11 is the mechanism. The container’s name and any --network-alias are registered in the DNS server, and the other containers on the same network can resolve them. The default bridge network uses the host’s DNS configuration and has no service discovery .


Why the default bridge lacks DNS resolution

The legacy problem. Before Docker 1.10, the only way to connect two containers by name was the --link option. The link created a static entry in the container’s /etc/hosts and injected environment variables. It was brittle: it hard-bound the container names, it did not tolerate restarts, and it did not work in both directions . When Docker introduced the embedded DNS server, it applied it only to the new user-defined networks. The default bridge kept the legacy behavior to avoid breaking the existing deployments .

The backward compatibility problem. The default bridge network inherits the host’s DNS configuration. If the host uses systemd-resolved with 127.0.0.53, the container inherits that address, and the address may not work inside the container’s network namespace. The user-defined network uses the embedded DNS server instead, which forwards external queries to the host’s DNS but handles the container names itself .

The isolation problem. The default bridge network is shared by all containers that do not specify a network. A container on the default bridge can reach any other container on the default bridge by IP address. The user-defined network isolates the containers from the other networks and provides the DNS resolution within the isolated group .

The service discovery problem. The user-defined network provides service discovery: the containers can find each other by name, and the names are resolved to the current IP addresses. The default bridge has no service discovery. The containers must use the IP addresses, which change when the containers restart .


a. The default bridge network

The default bridge network is created automatically when Docker starts. It is named bridge and backed by the docker0 interface with the 172.17.0.0/16 subnet .

docker network ls
# NETWORK ID     NAME      DRIVER    SCOPE
# 599dcaf4e856   bridge    bridge    local
# c817f1bca596   host      host      local
# e6508d3404a3   none      null      local

A container that does not specify a --network flag attaches to the default bridge.

docker run -d --name web nginx
docker network inspect bridge

The container gets an IP from the 172.17.0.0/16 range. The docker0 interface is the gateway, and the NAT rules route the outbound traffic .

The containers on the default bridge cannot resolve each other by name.

docker run -d --name db postgres
docker exec web ping db
# ping: bad address 'db'

The ping fails because the default bridge has no DNS entry for db. The container can reach db by its IP address, but the IP is not stable across restarts .

The default bridge network is not recommended for production. It is shared by all containers that do not specify a network, it has no DNS resolution, and the legacy --link option is the only way to provide the name resolution .


b. The user-defined bridge network

A user-defined bridge network is created explicitly with docker network create.

docker network create my-net
docker network inspect my-net

The network gets a subnet from the 172.18.0.0/16 range by default (the next available range after 172.17.0.0/16). The containers attached to the network get IPs from that subnet .

docker run -d --name web --network my-net nginx
docker run -d --name db --network my-net postgres

The two containers are on the same user-defined network. The embedded DNS server at 127.0.0.11 registers the container names, and the containers can resolve each other .

docker exec web ping db
# PING db (172.18.0.2): 56 data bytes

The ping succeeds because the DNS server resolves db to the container’s IP. The IP is dynamic; the DNS name is stable .

The user-defined network also provides isolation. The containers on my-net cannot reach the containers on the default bridge or on other user-defined networks unless they are explicitly connected .

The --network-alias option adds an additional DNS name on the user-defined network.

docker run -d --name db --network my-net --network-alias database postgres
docker exec web ping database

The database alias resolves to the same container as db. The alias is scoped to the network .


c. The DNS resolution mechanics

Docker’s embedded DNS server runs at 127.0.0.11 inside the container’s network namespace. The /etc/resolv.conf in the container points to that address on user-defined networks .

docker exec web cat /etc/resolv.conf
# nameserver 127.0.0.11
# options ndots:0

The DNS server handles three types of queries:

Query typeHandling
Container nameResolved by the embedded server
Network aliasResolved by the embedded server
External domainForwarded to the host’s DNS

The container name resolution works only for the containers on the same user-defined network. If the container is on multiple networks, the name is resolvable from the containers on each network .

The default bridge network does not use the embedded DNS server. The /etc/resolv.conf in the container points to the host’s DNS servers, and the container names are not registered .

docker run -d --name web nginx
docker exec web cat /etc/resolv.conf
# nameserver 192.168.1.1  (the host's DNS)

The web container cannot resolve db because the host’s DNS server knows nothing about the Docker container names .

The DNS resolution is the reason the user-defined network is the recommended default for multi-container applications. The containers can refer to each other by name, and the names are resolved to the current IPs. The configuration does not contain the IP addresses, which change when the containers restart .


Complete Example Session

# ============================================
# PART 1: DEFAULT BRIDGE
# ============================================
docker run -d --name web nginx
docker network inspect bridge
# ============================================
# PART 2: DEFAULT BRIDGE DNS FAILS
# ============================================
docker run -d --name db postgres
docker exec web ping db
# ping: bad address 'db'
# ============================================
# PART 3: CREATE USER-DEFINED NETWORK
# ============================================
docker network create my-net
docker network inspect my-net
# ============================================
# PART 4: RUN CONTAINERS ON USER-DEFINED NETWORK
# ============================================
docker run -d --name web2 --network my-net nginx
docker run -d --name db2 --network my-net postgres
# ============================================
# PART 5: DNS RESOLUTION WORKS
# ============================================
docker exec web2 ping db2
# PING db2 (172.18.0.2): 56 data bytes
# ============================================
# PART 6: CHECK DNS CONFIG
# ============================================
docker exec web2 cat /etc/resolv.conf
# nameserver 127.0.0.11
# ============================================
# PART 7: NETWORK ALIAS
# ============================================
docker run -d --name db3 --network my-net --network-alias database postgres
docker exec web2 ping database
# ============================================
# PART 8: CONNECT A CONTAINER TO A NETWORK
# ============================================
docker network connect my-net web
docker exec web ping db2
# ============================================
# PART 9: ISOLATION
# ============================================
docker network create other-net
docker run -d --name isolated --network other-net alpine sleep 1d
docker exec web2 ping isolated
# ping: bad address 'isolated'
# ============================================
# PART 10: LIST NETWORKS
# ============================================
docker network ls

The ten parts covered the default bridge, the DNS failure on the default bridge, the user-defined network creation, the containers on the user-defined network, the DNS resolution, the DNS configuration, the network alias, the container connection, the isolation, and the network listing.


Quick Reference

Default Bridge vs User-Defined Bridge

AspectDefault BridgeUser-Defined Bridge
CreatedAutomaticallyExplicitly
NamebridgeUser-specified
Subnet172.17.0.0/16172.18.0.0/16+
DNS resolutionNoYes (127.0.0.11)
Container name resolutionNoYes
Network aliasNoYes
IsolationSharedIsolated
Recommended for productionNoYes

DNS Resolution

QueryDefault BridgeUser-Defined Bridge
Container nameNoYes
Network aliasNoYes
External domainHost’s DNSHost’s DNS (forwarded)

Commands

CommandPurpose
docker network lsList networks
docker network create nameCreate user-defined network
docker network inspect nameInspect network
docker network connect net ctrConnect container to network
docker network disconnect net ctrDisconnect container
docker run --network netRun on network
docker run --network-alias aliasAdd DNS alias

DNS Configuration

FileContent
/etc/resolv.conf (user-defined)nameserver 127.0.0.11
/etc/resolv.conf (default bridge)Host’s DNS servers
Embedded DNS127.0.0.11

Best Practices

✅ Do This:

# Create a user-defined network for the application
docker network create app-net                                  # ✅

# Run all the application containers on the same network
docker run -d --name db --network app-net postgres             # ✅

# Use the container name in the application configuration
DB_HOST=db                                                     # ✅

# Use network aliases for the additional names
docker run --network-alias database --network app-net postgres # ✅

# Inspect the network to verify the containers
docker network inspect app-net                                 # ✅

# Connect the running containers to the network when needed
docker network connect app-net web                             # ✅

❌ Don’t Do This:

# Don't use the default bridge for the multi-container apps
docker run -d --name db postgres                               # ❌ no DNS

# Don't hardcode the container IPs in the configuration
DB_HOST=172.17.0.2                                             # ⚠️ changes on restart

# Don't expect the DNS resolution across the networks
docker exec web ping db  # if web and db are on different nets  # ❌

# Don't rely on the default bridge for the service discovery
docker run -d --name db postgres                               # ⚠️

# Don't forget the network alias scope
docker run --network-alias database --network app-net postgres # ✅ but only on app-net

# Don't use the --link option for the new deployments
docker run --link db:db web                                    # ⚠️ legacy

# Don't forget that the default bridge inherits the host's DNS
docker run -d --name web nginx                                 # ⚠️ host DNS

Common Pitfalls

PitfallWhy It HappensFix
Container name not resolvedDefault bridgeUse user-defined bridge
DNS resolution failsDifferent networksConnect to the same network
IP address changesContainer restartUse the DNS name
Alias not resolvedAlias on a different networkUse the alias on the same network
ping: bad addressNo DNS entryCheck the network and the name
External DNS failsHost’s DNS misconfiguredCheck the host’s /etc/resolv.conf
Container cannot reach anotherDifferent networksConnect to the same network

Real-World Examples

1. Default Bridge (No DNS)

docker run -d --name web nginx
docker run -d --name db postgres
docker exec web ping db  # fails

2. User-Defined Bridge (DNS)

docker network create app-net
docker run -d --name web --network app-net nginx
docker run -d --name db --network app-net postgres
docker exec web ping db  # works

3. Network Alias

docker run -d --name db --network app-net --network-alias database postgres
docker exec web ping database

4. Connect a Container

docker network connect app-net web

5. Inspect the Network

docker network inspect app-net

6. Check DNS Configuration

docker exec web cat /etc/resolv.conf

7. List Networks

docker network ls

8. Isolate the Containers

docker network create isolated-net
docker run -d --name app --network isolated-net alpine

9. Docker Compose

services:
  web:
    image: nginx
  db:
    image: postgres
# Compose creates a user-defined network by default

10. Clean Up

docker network rm app-net

Visual

Default Bridge vs User-Defined Bridge

┌─────────────────────────────────────────────────────────────┐
│  DEFAULT BRIDGE (docker0)                                   │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  Container A (172.17.0.2)                           │    │
│  │  Container B (172.17.0.3)                           │    │
│  │                                                     │    │
│  │  No DNS resolution between containers.              │    │
│  │  Can only use IP addresses.                         │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  USER-DEFINED BRIDGE (app-net)                              │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  Embedded DNS (127.0.0.11)                          │    │
│  │  ┌─────────────────────────────────────────────┐    │    │
│  │  │  Container A (172.18.0.2)  name: "web"      │    │    │
│  │  │  Container B (172.18.0.3)  name: "db"       │    │    │
│  │  └─────────────────────────────────────────────────────┘    │
│  │                                                     │    │
│  │  DNS resolution works. Names are stable.            │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

DNS Resolution Flow

┌─────────────────────────────────────────────────────────────┐
│  Container A: ping db                                       │
│    │                                                        │
│    ▼                                                        │
│  /etc/resolv.conf → nameserver 127.0.0.11                   │
│    │                                                        │
│    ▼                                                        │
│  Embedded DNS server                                        │
│    │                                                        │
│    ├── "db" is a container name ──▶ resolve to 172.18.0.3   │
│    │                                                        │
│    └── external domain ──▶ forward to host's DNS            │
│                                                             │
│  The embedded DNS server knows the container names.         │
│  The host's DNS server does not.                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Isolation

┌─────────────────────────────────────────────────────────────┐
│  app-net (172.18.0.0/16)                                    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  web, db, cache                                     │    │
│  │  Can resolve each other by name.                    │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  other-net (172.19.0.0/16)                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  app, worker                                        │    │
│  │  Cannot resolve the containers on app-net.          │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  The networks are isolated by default.                      │
│  Use docker network connect to join them.                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Docker Compose Default Network

┌─────────────────────────────────────────────────────────────┐
│  docker-compose.yml                                         │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  services:                                          │    │
│  │    web:                                             │    │
│  │      image: nginx                                   │    │
│  │    db:                                              │    │
│  │      image: postgres                                │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  Compose creates a user-defined network automatically.      │
│  The service names (web, db) are the DNS names.             │
│  The containers can resolve each other by the service name. │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Summary

ItemValue
Default bridgedocker0, 172.17.0.0/16
Default bridge DNSNo container name resolution
User-defined bridgeCreated explicitly
User-defined DNS127.0.0.11 embedded server
Container name resolutionUser-defined only
Network aliasUser-defined only
IsolationPer network
RecommendedUser-defined bridge
Legacy--link on default bridge
ComposeCreates user-defined by default

Key takeaways:

  • The default bridge network does not resolve container names. The containers can only communicate by IP address. The default bridge inherits the host’s DNS configuration, which knows nothing about the Docker container names .
  • The user-defined bridge network provides DNS resolution. Docker runs an embedded DNS server at 127.0.0.11 inside the container’s network namespace. The server resolves the container names and the network aliases .
  • The container name resolution is the service discovery. The containers can refer to each other by name, and the name is resolved to the current IP address. The IP addresses change when the containers restart, but the names do not .
  • The user-defined network provides isolation. The containers on one user-defined network cannot reach the containers on another unless they are explicitly connected. The isolation is the security boundary and the organizational boundary .
  • The --network-alias option adds an additional DNS name. The alias is scoped to the network. The containers on the same network can resolve the alias to the container’s IP .
  • The Docker Compose creates a user-defined network automatically. The service names in the Compose file are the DNS names. The containers can resolve each other by the service name .
  • The default bridge is not recommended for production. It is shared by all containers, it has no DNS resolution, and the --link option is the only way to provide the name resolution. The user-defined bridge is the recommended default for the multi-container applications .

Remember: The default bridge network and the user-defined bridge network are different in a way that matters for the multi-container applications. The default bridge has no DNS resolution, which means the containers can only communicate by IP address. The user-defined bridge has the embedded DNS server, which resolves the container names and the aliases. The user-defined network is the recommended default for the applications that have more than one container. Create the network, run the containers on it, and refer to the other containers by name. The names are stable, the IPs are not. And remember that the Docker Compose creates the user-defined network automatically, which is one of the reasons it is the preferred tool for the multi-container applications.



Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!