Let containers talk to each other and to you — put containers on a user-defined network so they reach each other by name, and understand publishing ports versus internal ports.
Containers on the same user-defined network can reach each other by container name — Docker runs a tiny DNS server that resolves the name to the right container. Create a network, start your database and app on it, and the app connects to the database at the host "db", no IP addresses needed.
1. Create a network
docker network create appnet2. Run the database on it
docker run -d --name db --network appnet \
-e POSTGRES_PASSWORD=secret postgres:163. Run the app on it — inside the app, the DB host is just "db"
docker run -d --name api --network appnet \
-e DATABASE_URL=postgres://postgres:secret@db:5432/postgres \
myappTwo containers on the same network reach each other on the container port directly (db:5432) — no -p needed. You only publish a port with -p when YOU, from the host, need to reach the container. So your API publishes 3000 to the world, but the database stays unpublished and is reachable only by other containers on the network.
API is reachable from your browser (published)
docker run -d --name api --network appnet -p 3000:3000 myappDB is reachable only by containers on appnet (NOT published) — safer: nothing outside Docker can connect to it
docker run -d --name db --network appnet \
-e POSTGRES_PASSWORD=secret postgres:16See what's attached to the network
docker network inspect appnet