Skip to content

Multi-Service Apps

Almost every real application needs a database. With Docker Compose you define both services in one file and Compose handles the networking automatically — no manual docker network create required.

Here is a web app backed by PostgreSQL:

services:
app:
image: node:22-alpine
working_dir: /app
command: ["node", "server.js"]
ports:
- "3000:3000"
environment:
- DATABASE_HOST=db
- DATABASE_PORT=5432
- DATABASE_NAME=mydb
depends_on:
- db
db:
image: postgres:17-alpine
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=secret

depends_on tells Compose to start the db service before app. This controls container start order, not readiness — the database process inside the container may not be accepting connections the instant the container starts. For production, add a healthcheck to db and use depends_on: condition: service_healthy in app.

Basic start order (sufficient for learning and development):

depends_on:
- db

Health-checked start order (production pattern):

services:
app:
depends_on:
db:
condition: service_healthy
db:
image: postgres:17-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 5s
timeout: 5s
retries: 5
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=secret

When you run docker compose up, Compose automatically creates a network for your project. Every service in the file is attached to that network. Services reach each other using their service name as the hostname.

In the example above, app connects to the database at host db port 5432 — exactly the service name. No IP addresses, no manual network configuration.

app --[db:5432]--> db
<-- myapp-network (auto-created) -->

Stream logs from all services at once:

Terminal window
docker compose logs -f

Follow only one service:

Terminal window
docker compose logs -f app

The snippet below starts an app container that connects to a PostgreSQL container using the service name db.

# Write a two-service compose.yaml
cat > compose.yaml <<'EOF'
services:
  app:
    image: alpine
    command: >
      sh -c "
        echo 'Waiting for db...' &&
        sleep 3 &&
        echo 'Connecting to db:5432 (postgres service)' &&
        nc -zv db 5432 &&
        echo 'Connection to db succeeded via service name DNS!'
      "
    depends_on:
      - db

  db:
    image: postgres:17-alpine
    environment:
      - POSTGRES_PASSWORD=secret
EOF

# Start both services (app waits 3s then probes db)
docker compose up

# Clean up
docker compose down
How does the app service connect to the database in a Compose app?
What does depends_on: - db guarantee?
Which command streams logs from all services simultaneously?
What creates the internal network that connects all Compose services?