Good Code
The good version names persistence, keeps services on an internal network, and exposes only the application port needed by the host.
Lesson 10
Use Compose to define service boundaries, persistent volumes, and internal networks without overexposing ports or state.
services:
app:
build: .
environment:
DATABASE_HOST: db
depends_on:
db:
condition: service_healthy
# Only expose the web port the host needs.
ports:
- "3000:3000"
networks:
- internal
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: reviews
POSTGRES_USER: reviews
# Named volumes keep database data after container restarts.
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U reviews"]
interval: 10s
timeout: 5s
retries: 5
# Services talk to each other on a private network.
networks:
- internal
volumes:
postgres_data:
networks:
internal:services:
app:
build: .
# Host networking removes the boundary between container and host.
network_mode: host
volumes:
- .:/app
# Mounting / exposes the host filesystem to the container.
- /:/host
db:
image: postgres:latest
# Opening the database port is often unnecessary for app-only access.
ports:
- "5432:5432"The good version names persistence, keeps services on an internal network, and exposes only the application port needed by the host.
The bad version uses host networking, mounts the host filesystem, and exposes the database without a clear reason.