version: '3.8' services: # 1. PostgreSQL Database Service postgres: image: postgres:16-alpine container_name: url_shortener_db environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: url_shortener ports: - "5432:5432" volumes: # Persistent PostgreSQL data storage volume - postgres_data:/var/lib/postgresql/data # Automated schema DDL migration script for initial empty data directory - ./schema.sql:/docker-entrypoint-initdb.d/01_schema.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d url_shortener"] interval: 5s timeout: 5s retries: 5 restart: unless-stopped # 2. Node.js / Express Application Service app: build: . container_name: url_shortener_app ports: - "3000:3000" environment: NODE_ENV: production PORT: 3000 # Container-to-container database connection using service name 'postgres' DATABASE_URL: postgres://postgres:postgres@postgres:5432/url_shortener depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/ready', (r) => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"] interval: 10s timeout: 5s retries: 3 start_period: 5s restart: unless-stopped volumes: # Persistent storage for PostgreSQL data postgres_data: