Docker Networking Explained: Bridge, Host, and Overlay Modes

Learn how Docker networking works with practical examples. This tutorial covers bridge, host, overlay, and macvlan network modes with hands-on commands.

Diagram showing Docker containers connected through different network modes

Every Docker container needs a way to talk to other containers, the host machine, or the outside world. Networking makes that happen. But Docker offers several network modes, and picking the wrong one can lead to hours of debugging “connection refused” errors.

This tutorial walks you through each Docker network mode with real commands you can run on your own server. By the end, you will know which mode fits your use case and how to set it up.

Prerequisites

Before you start, make sure you have:

  • Docker Engine 20.10 or later installed
  • Basic familiarity with the Linux command line
  • A Linux server or local machine with Docker running

Check your Docker version:

docker --version

How Docker Networking Works

When Docker starts on a Linux host, it creates a virtual bridge called docker0. Every new container connects to this bridge by default. The container gets its own network namespace with a virtual Ethernet pair (veth). One end stays inside the container. The other end plugs into the bridge on the host.

This setup gives each container its own IP address, routing table, and DNS configuration. Containers on the same bridge can reach each other by IP. Containers on different networks cannot, unless you connect them.

Docker provides these built-in network drivers:

DriverDescriptionUse Case
bridgeIsolated network on a single hostMost single-host setups
hostShares the host network stackHigh-performance apps
noneNo networking at allSecurity-sensitive workloads
overlayConnects containers across multiple hostsDocker Swarm clusters
macvlanAssigns a real MAC address to containersLegacy app integration

List your current Docker networks:

docker network ls

Bridge Network: The Default Choice

Bridge is the default network driver. When you run a container without specifying --network, Docker attaches it to the default bridge.

The Default Bridge vs. Custom Bridge

The default bridge has a limitation: containers can only reach each other by IP address, not by name. Custom bridge networks fix this by enabling built-in DNS resolution.

Create a custom bridge network:

docker network create --driver bridge app-network

Run two containers on this network:

docker run -d --name web --network app-network nginx:latest
docker run -d --name api --network app-network node:18-alpine sleep infinity

Now test name-based communication:

docker exec api ping -c 3 web

This works because custom bridge networks include an embedded DNS server that resolves container names to IP addresses.

Custom Subnet Configuration

You can control the IP range for your bridge network:

docker network create \
  --driver bridge \
  --subnet 192.168.100.0/24 \
  --gateway 192.168.100.1 \
  --ip-range 192.168.100.128/25 \
  my-custom-bridge

Assign a fixed IP to a container:

docker run -d \
  --name fixed-ip-app \
  --network my-custom-bridge \
  --ip 192.168.100.150 \
  nginx:latest

When to Use Bridge Networks

  • Development environments on a single host
  • Microservices that need to communicate locally
  • Isolated application stacks
  • Testing setups where you want containers separated from the host

Host Network: Maximum Performance

Host mode removes the network isolation between the container and the Docker host. The container uses the host’s IP address and network interfaces directly. No NAT, no port mapping.

Run a container with host networking:

docker run -d --name host-nginx --network host nginx:latest

Nginx is now accessible on port 80 of your host’s IP address. You do not need -p 80:80 because there is no network translation layer.

Performance Comparison

Host networking eliminates the overhead of the virtual bridge and NAT. For network-heavy applications, this can make a measurable difference:

  • Bridge mode: Packets go through veth pair, bridge, and iptables NAT rules
  • Host mode: Packets go directly through the host’s network stack

Limitations

  • Only works on Linux (on macOS and Windows, Docker runs inside a VM)
  • Port conflicts with host services are possible
  • No network isolation between the container and host
  • You cannot run two containers that bind to the same port

Check for port conflicts before using host mode:

ss -tlnp | grep :80

When to Use Host Networks

  • Applications that need the lowest possible network latency
  • Network monitoring or packet capture tools
  • Services that bind to many ports dynamically
  • Performance benchmarking

None Network: Complete Isolation

The none driver disables all networking for a container. It only has a loopback interface (127.0.0.1). No communication with other containers or external networks.

docker run -d --name isolated --network none alpine:latest sleep infinity

Verify the container has no external access:

docker exec isolated ip addr
# Only shows the loopback interface

docker exec isolated ping -c 1 8.8.8.8
# ping: sendto: Network is unreachable

Practical Example: Secure Data Processing

Run a container that processes sensitive files without any network access:

docker run -d \
  --name secure-processor \
  --network none \
  -v /data/input:/input:ro \
  -v /data/output:/output \
  data-processor:latest

The container reads from /input and writes to /output. No data can leave through the network.

When to Use None Networks

  • Batch jobs that only work with local files
  • Security-sensitive workloads that must not access the network
  • Compliance requirements that mandate full network isolation

Overlay Network: Multi-Host Communication

Overlay networks let containers on different Docker hosts communicate as if they were on the same local network. This is the networking backbone of Docker Swarm.

Setting Up an Overlay Network

First, initialize Docker Swarm on your manager node:

docker swarm init --advertise-addr <MANAGER-IP>

Join worker nodes:

docker swarm join --token <TOKEN> <MANAGER-IP>:2377

Create an overlay network:

docker network create \
  --driver overlay \
  --subnet 10.0.0.0/24 \
  my-overlay

Deploying Services

docker service create \
  --name web \
  --network my-overlay \
  --replicas 3 \
  nginx:latest

docker service create \
  --name api \
  --network my-overlay \
  --replicas 2 \
  node:18-alpine

The web service can reach api by name, even when replicas run on different hosts.

Encrypted Overlay Networks

Enable IPsec encryption for sensitive traffic:

docker network create \
  --driver overlay \
  --opt encrypted \
  secure-overlay

All container-to-container traffic on this network is encrypted automatically.

When to Use Overlay Networks

  • Docker Swarm deployments across multiple servers
  • Microservices that span several hosts
  • High-availability setups with service replication

Docker Compose Networking

Docker Compose creates a default network for each project automatically. All services in a docker-compose.yml file can reach each other by service name.

services:
  frontend:
    image: nginx:latest
    networks:
      - frontend-net
    ports:
      - "80:80"

  api:
    image: node:18-alpine
    networks:
      - frontend-net
      - backend-net

  database:
    image: postgres:16
    networks:
      - backend-net
    environment:
      POSTGRES_PASSWORD: secret

networks:
  frontend-net:
  backend-net:

In this setup:

  • frontend and api share frontend-net, so the Nginx container can proxy requests to api
  • api and database share backend-net, so the API can query Postgres at database:5432
  • frontend cannot reach database directly, which improves security

This pattern of network segmentation keeps your database isolated from public-facing services.

Networking Best Practices

1. Always use custom bridge networks. The default bridge lacks DNS resolution and provides less isolation. Create a named network for each application stack.

2. Segment your networks by tier. Put frontend, backend, and database containers on separate networks. Connect only the services that need to talk to each other.

3. Expose only the ports you need. Every open port is a potential attack surface. Use -p carefully and avoid -P (which publishes all exposed ports).

# Good: only expose port 80
docker run -d -p 80:80 --network app-net nginx:latest

# Avoid: exposes all ports defined in the Dockerfile
docker run -d -P --network app-net nginx:latest

4. Use DNS names instead of IP addresses. Container IPs can change when containers restart. Service names on custom networks are stable and reliable.

5. Monitor network traffic. Use docker stats to watch network I/O:

docker stats --format "table {{.Name}}\t{{.NetIO}}"

Troubleshooting Common Issues

Containers Cannot Reach Each Other

Verify both containers are on the same network:

docker network inspect app-network

Look for both container names in the Containers section. If one is missing, connect it:

docker network connect app-network <container-name>

DNS Resolution Fails

This happens on the default bridge network, which does not support name resolution. Move your containers to a custom network:

docker network create my-net
docker network connect my-net <container-name>

Check the DNS config inside a container:

docker exec <container-name> cat /etc/resolv.conf

Container Cannot Access the Internet

Check if IP forwarding is enabled on the host:

sysctl net.ipv4.ip_forward

If the value is 0, enable it:

sudo sysctl -w net.ipv4.ip_forward=1

Also verify that iptables is not blocking traffic:

sudo iptables -L -n -t nat

Quick Reference

TaskCommand
List networksdocker network ls
Create bridge networkdocker network create my-net
Run container on networkdocker run --network my-net ...
Connect running containerdocker network connect my-net <name>
Disconnect containerdocker network disconnect my-net <name>
Inspect networkdocker network inspect my-net
Remove networkdocker network rm my-net
Remove unused networksdocker network prune

Summary

Docker networking controls how containers communicate. The five built-in drivers cover most scenarios:

  • Bridge works for single-host setups and is the right default for most projects
  • Host gives you raw performance at the cost of isolation
  • None locks down containers that should never touch the network
  • Overlay connects containers across multiple Docker hosts
  • Macvlan makes containers appear as physical devices on your LAN

Start with custom bridge networks for development. Use Docker Compose to define network segmentation in code. Move to overlay networks when you scale to multiple hosts.

For more Docker tutorials, check out our guides on Docker Compose on Ubuntu 22.04, Docker Volume Management, and Docker Security Best Practices.