Docker networking cheatsheet.

Network drivers

  • bridge (default): isolated network on host.
  • host: container shares host’s network stack (Linux).
  • none: no networking.
  • overlay: multi-host (Swarm).
  • macvlan: container gets its own MAC + IP on host network.

bridge basics

docker network create mynet
docker run -d --name a --network mynet alpine sleep 1000
docker run -d --name b --network mynet alpine sleep 1000

docker exec a ping b                   # works (DNS by name)
docker exec a getent hosts b

User-defined bridge networks have automatic DNS between containers. The default bridge does NOT.

host network (Linux only)

docker run -d --network host nginx

Container uses host’s network — no port mapping needed. Use sparingly (security, port conflicts).

Multiple networks

docker run -d --name web --network frontend nginx
docker network connect backend web

Container reachable on both networks.

Port publishing

docker run -p 8080:80 nginx                  # host:container
docker run -p 127.0.0.1:8080:80 nginx        # bind specific interface
docker run -p 8080:80/udp app
docker run -p 8080-8090:8080-8090 app        # range
docker run -P nginx                           # random host ports

DNS

Containers on user-defined networks resolve each other by:

  • Container name (--name web).
  • Network alias (--network-alias myname).
  • Service name (compose).
docker run -d --network mynet --name web --network-alias api app
# Both `web` and `api` resolve to this container.

Container IP

docker inspect --format='{{.NetworkSettings.Networks.mynet.IPAddress}}' web

Don’t rely on IPs — they change. Use names.

Internal-only network

docker network create --internal backend

No external connectivity. Good for DBs.

DNS to host

On Docker Desktop (Mac/Windows): host.docker.internal resolves to host.

On Linux: add it manually:

docker run --add-host=host.docker.internal:host-gateway app

/etc/hosts

docker run --add-host=api.local:1.2.3.4 app
docker run -d --link db:db app

Replaced by user-defined networks. Avoid.

Compose networks

services:
  web: { networks: [frontend, backend] }
  db: { networks: [backend] }
  proxy: { networks: [frontend] }

networks:
  frontend:
  backend:
    internal: true

Inspect

docker network ls
docker network inspect mynet
docker network inspect mynet --format='{{json .Containers}}' | jq

ipam (IP address management)

docker network create \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  --ip-range 172.20.1.0/24 \
  mynet

docker run --network mynet --ip 172.20.1.100 app

Specific IPs (rarely needed).

Limit bandwidth (with tc on host)

Docker doesn’t natively limit BW. Use tc on the container’s interface or run in K8s with CNI that supports it.

Troubleshooting

# Can a → b?
docker exec a ping b
docker exec a nc -zv b 80
docker exec a curl -v http://b/

# Is the port open inside container?
docker exec b netstat -tlnp        # or ss -tlnp

# Is it published on host?
docker port web
netstat -tlnp | grep 8080            # host

Common issues

“Connection refused”

App listens on 127.0.0.1:8000 inside container; from host you get refused. Fix: app must bind 0.0.0.0.

“Address already in use”

Host port taken. Stop the conflicting container or pick another port.

DNS not resolving

You’re on the default bridge network. Move to a user-defined network.

Slow DNS

On Linux with systemd-resolved, container may use the host’s resolver. Add --dns 1.1.1.1 to bypass.

MACVLAN (container with real IP)

docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  publicnet

docker run --network publicnet --ip 192.168.1.50 nginx

Useful for legacy networking. Limitations: host can’t reach container by default (loopback isolation).

Overlay (Swarm / multi-host)

docker swarm init
docker network create -d overlay mynet
docker service create --network mynet --name web nginx

Containers across hosts can talk via the overlay network.

Reverse proxy + internal services

services:
  proxy:
    image: caddy
    ports: ["80:80", "443:443"]
    networks: [public, internal]
  
  api:
    build: .
    networks: [internal]
  
  worker:
    build: .
    networks: [internal]

networks:
  public:
  internal:
    internal: true

Only proxy exposed publicly.

Common mistakes

  • Using localhost in container to reach another container — localhost is the container.
  • Hardcoded container IPs.
  • Forgetting --network mynet → containers on different networks can’t talk.
  • Default bridge with multiple containers — no DNS by default.
  • Publishing port without binding to interface in dev → exposed to LAN.

Read this next

If you want my network + reverse-proxy patterns, they’re at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .