CD2: Running many containers together
Networks and names
🎯You'll be able to
Put containers on a private network where they find each other by name, and decide which ports, if any, are published to the outside.
🏠The everyday picture
In an office building, colleagues call each other on short internal extensions ("dial 214 for accounts"). Only the reception desk has a number that outsiders can call. Nobody gives the accounts team's extension to the public.
📘What it really is
-
Docker creates networks. Containers on the same user-defined network can reach each other, and Docker's built-in DNS server (at
127.0.0.11inside each container) answers their names. So the API connects topostgres://...@db:5432/..., wheredbis a name, not an address. -
The default bridge network (what you get without naming one) doesn't offer this name lookup. Always create your own network.
-
Aliases: a container can have extra names on a network. In RouteRani, every API copy has the alias
app; asking DNS forappreturns all their addresses. -
Publishing a port (
-p 8080:80, or aportsblock in Terraform or Compose) connects a port on the host computer to a port in the container. Without it, the container is reachable only from its network. -p 8080:80listens on every network interface of the host, so other computers on the network can reach it.-p 127.0.0.1:8080:80listens only on the host itself.- On Linux, Docker sets up its own firewall rules for published ports, which can bypass a host firewall such as
ufw. Don't rely on the host firewall to hide a published database. localhostinside a container means that container. An API that connects tolocalhost:5432looks for a database inside its own container and fails. Use the other container's name.
📝A worked example
Input: in the RouteRani kit, terraform apply in infra/, then docker network inspect routerani-dev and
docker exec routerani-dev-lb nslookup app 127.0.0.11.
Expected output: the network lists the database, the API copies and the load balancer. The lookup returns one address per API copy (two
once Project 1 adds a second copy). docker port routerani-dev-db shows 5432/tcp -> 0.0.0.0:15432 in the starter, meaning anyone who can
reach your computer can try to sign in to the database. Project 1 removes that.
🌍Where it's used
- Every multi-container app: API to database, API to cache, worker to queue.
- Cloud networks follow the same idea at a bigger scale: private subnets for databases, a public load balancer only (CD6).
- Security reviews ask "which ports are published, and why?" first.
📝Case scenario
A coaching institute's student portal ran PostgreSQL in Docker with -p 5432:5432 "just for debugging", on a cloud server with a public
address. Automated scanners found it within hours and tried thousands of passwords. Because the password was postgres123, they got in and
copied the student list. A private network, no published port and a strong generated password would each have stopped it.
🖱️Try it
Run docker run --rm --network routerani-dev alpine nslookup db and then the same with --network bridge. Success: the first finds db,
the second can't, because only user-defined networks have the name lookup.
⚠️Common mistakes
- Publishing the database "for now". Sign:
docker psshows0.0.0.0:5432->5432. Fix: remove the port; usedocker exec ... psqlto look inside. - Using
localhostbetween containers. Sign: "connection refused" from the API although the database is running. Fix: connect to the container's name. - Hard-coding container IP addresses. Sign: the app breaks after a restart, when addresses change. Fix: use names and aliases.
🛠️For your project
Project 1 test 6 fails if the database container has any port published on your computer.
✅Quick check
How does the RouteRani API find the database?
Show the answer
By the name db, which Docker's DNS answers on the shared network.
What does -p 127.0.0.1:8080:80 change compared with -p 8080:80?
Show the answer
Only the host itself can reach port 8080, not other computers.
