Chapter 11 of 16 · Visual guide

Container-to-container communication

Containers must find each other by name, and you decide who may talk to whom by choosing which networks they join.

key idea / Docker itselfcontainer / good pathhost / watch outproblem / blockedneutral

The IP address trap

The IP trapThe web container uses a hard-coded IP for the database. After the database restarts it gets a new IP and the connection fails.Mondaywebdb172.17.0.3connects to 172.17.0.3:5432: worksAfter db restartswebdbnow 172.17.0.5still dials .3: connection refusedFix: call db by name. Docker DNS returns whatever IP it has now.
Never hard-code a container IP. Use its name on a user-defined network.

How a request finds its target

What happens when web calls http://api:80Web asks the embedded DNS for api, receives its IP, then sends the packet over its veth to the bridge, which forwards it to the api container.webDocker DNSbridgeapi1 who is "api"?2 api = 172.18.0.33 packet to 172.18.0.3 via veth4 forwarded by MAC5 response

Networks as walls

Networks as wallsThe web and api containers share frontend-net. The api and db share backend-net. Web and db share no network, so web cannot reach db.frontend-netbackend-netwebfrontendapiboth netsdbbackendweb to db: no shared network, so no route and no DNS name
Group containers by who must talk to whom. The api straddles both networks; web and db never meet.

Default bridge versus user-defined

FeatureDefault bridgeUser-defined network
Name resolutionNo, IP onlyYes, container name
IsolationAll containers share one networkYou group containers
Set upautomaticdocker network create
Attach a running containernodocker network connect

Try it yourself

Build the three-tier layout from the diagram and prove the wall works.

  1. Step 1 · Two networks and the database
    $ docker network create frontend-net
    $ docker network create backend-net
    $ docker run -d --name db --rm --network backend-net alpine:3.20 sleep 300
  2. Step 2 · The api starts on one network, then joins the second

    network connect adds a second endpoint, so the api can see both sides.

    $ docker run -d --name api --rm --network frontend-net alpine:3.20 sleep 300
    $ docker network connect backend-net api
    $ docker run -d --name web --rm --network frontend-net alpine:3.20 sleep 300
  3. Step 3 · web reaches api by name, not db
    $ docker exec web ping -c 1 api
    64 bytes from 172.18.0.3: seq=0 ttl=64
    $ docker exec web ping -c 1 db
    ping: bad address 'db'
  4. Step 4 · api reaches db
    $ docker exec api ping -c 1 db
    64 bytes from 172.19.0.2: seq=0 ttl=64
    $ docker stop web api db
    $ docker network rm frontend-net backend-net

Recap

Quick check

The frontend can ping the API but not the database. Which single setting explains this?
Show answer

Network membership. The database is only on backend-net, the frontend only on frontend-net. With no shared network there is neither a route nor a DNS name.