The networking lesson introduced the idea that containers on the same user-defined network can reach each other by name. This lesson goes underneath that: what each network driver actually does, how Docker's embedded DNS resolves names and aliases, how to publish ports safely, and how to isolate services so a compromised front end cannot talk directly to the database.
| Driver | What it does | Typical use |
|--------|--------------|-------------|
| bridge | Private virtual switch on the host; containers get their own IPs and NAT to the outside | Default for single-host apps |
| host | No isolation; the container shares the host's network stack and ports | High-performance or port-heavy tools on Linux |
| none | Only a loopback interface; no external connectivity | Batch jobs that must not reach the network |
| overlay | Spans multiple hosts | Swarm services |
| macvlan | Gives the container a MAC and IP on the physical LAN | Legacy apps that need to appear as real hosts |
docker network ls
docker run --rm --network host nginx:alpine # listens directly on host port 80
docker run --rm --network none alpine ping -c1 1.1.1.1 # Network unreachablehost networking is Linux-native; Docker Desktop offers it as an opt-in setting. -p is ignored with --network host because there is nothing to map.
Every daemon has a network named bridge (interface docker0) that containers join when you pass no --network. It is deliberately limited: containers can reach each other only by IP address, and the legacy --link flag is the only way to add names. A user-defined bridge adds:
--network-alias.docker network connect and disconnect.docker network create --driver bridge --subnet 10.10.0.0/24 app-net
docker run -d --name redis --network app-net redis:7-alpine
docker run --rm --network app-net redis:7-alpine redis-cli -h redis ping # PONGCompose creates one user-defined network per project automatically, which is why service names just work there.
Inside a container on a user-defined network, /etc/resolv.conf points to 127.0.0.11, Docker's embedded DNS server. It answers for container names, network aliases and Compose service names, and forwards everything else to the host's resolvers. Several containers can share one alias, in which case the resolver returns all their IPs, a crude form of load balancing.
docker run -d --network app-net --network-alias cache redis:7-alpine
docker run -d --network app-net --network-alias cache redis:7-alpine
docker run --rm --network app-net alpine nslookup cache # two addressesNames are resolvable only within a shared network. A container attached to two networks can act as a bridge between them, which is the pattern used to expose an API to a proxy while keeping the database private.
Outbound traffic from a bridge network is NATed through the host, so containers can reach the internet without any flags. Reaching a service on the host (a local database, for example) uses the special name host.docker.internal, which Docker Desktop provides automatically. On Linux, add it explicitly:
docker run --rm --add-host=host.docker.internal:host-gateway alpine \
wget -qO- http://host.docker.internal:8000/A network created with --internal has no route to the outside at all, which is ideal for databases and queues.
-p maps a host port to a container port and, by default, binds to all host interfaces. That exposes the service to the network the host is on, bypassing many host firewalls because Docker manipulates iptables directly.
docker run -d -p 8080:80 nginx:alpine # 0.0.0.0:8080 -> 80: reachable from LAN
docker run -d -p 127.0.0.1:8080:80 nginx:alpine # loopback only
docker run -d -P my-api:1.0 # random host ports for each EXPOSE
docker port <container>Publish only the entry point (a reverse proxy or the API), bind development ports to 127.0.0.1, and leave databases unpublished; other containers reach them over the internal network without any host port.
bridge network and wondering why ping db fails; create a user-defined network.localhost inside a container to mean the host; it means the container itself.Why can containers on a user-defined bridge reach each other by name, while those on the default bridge cannot?
bridge is the default and NATs outbound traffic; host removes isolation; none removes connectivity.127.0.0.11 resolves names only within a shared network; multi-network containers bridge tiers.host.docker.internal reaches the host; --internal networks have no external route.127.0.0.1, and never publish databases.Next lesson: Environment Variables and Configuration — pass settings into containers with -e, env files and Compose.