Build Elevate

Docker

Production-ready Docker configurations using Docker Compose for containerizing and orchestrating all monorepo applications

Docker & Containerization

The monorepo includes production-ready Docker configurations for building and deploying all applications.

Overview

The Docker setup provides a robust, secure foundation for both development and production:

  • Multi-stage Dockerfiles - Optimized images for web and API with minimal size
  • Docker Compose - Orchestrate all services (web, API, database, Redis)
  • Non-root Execution - Improved security by running containers as non-root users
  • Health Checks - Services verify readiness before dependent services start
  • Turbo Pruning - Faster builds with optimized dependency installation
  • Development Environment - Simplified docker-compose for local development

Development Setup

For local development, use the docker-compose.yml file in the repository root:

docker-compose up -d

This starts the PostgreSQL database for development:

  • PostgreSQL - localhost:5432
  • Database - build-elevate-app
  • User - postgres
  • Password - password

Development Docker Compose Structure

The development setup includes:

services:
  postgres:
    image: postgres:16-alpine
    container_name: build-elevate-postgres-dev
    environment:
      POSTGRES_DB: build-elevate-app
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    ports:
      - 5432:5432
    volumes:
      - build-elevate-app_postgres_data_dev:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

The development docker-compose uses hardcoded credentials for convenience. Never use these credentials in production.

Common Development Commands

# Start PostgreSQL
docker-compose up -d

# Stop PostgreSQL
docker-compose down

# View logs
docker-compose logs -f postgres

# Connect to database directly
docker-compose exec postgres psql -U postgres -d build-elevate-app

# Remove volume and start fresh
docker-compose down -v && docker-compose up -d

Production Deployment

To build and run the full stack in production mode:

pnpm docker:prod

This will start:

Production Configuration

Production deployments use docker-compose.prod.yml with optimized settings:

docker-compose -f docker-compose.prod.yml up -d

Production setup includes:

  • Multi-stage optimized builds
  • Minimal image sizes
  • Non-root user execution
  • Security hardening
  • Health checks and monitoring

Key Files & Structure

FilePurpose
docker-compose.prod.ymlProduction orchestration with optimized settings
apps/web/Dockerfile.prodMulti-stage build for Next.js frontend
apps/api/Dockerfile.prodMulti-stage build for Express backend

Dockerfiles: Multi-Stage Builds

Both web and API Dockerfiles use a multi-stage build approach:

Stage 1: Builder
  ├─ Install dependencies
  ├─ Run build/compilation
  └─ Generate artifacts

Stage 2: Runtime
  ├─ Copy only artifacts from builder
  ├─ Install runtime dependencies only
  └─ Run application

This approach results in minimal production images by excluding build tools and dependencies.

Environment Configuration

Set environment variables for Docker containers in production (docker-compose.prod.yml):

environment:
  DATABASE_URL: ${DATABASE_URL}
  NODE_ENV: production

Production values should be set via your deployment platform secrets.

Best Practices

Security

  • Non-root Users - All containers run as non-root users (e.g., appuser:appuser)
  • Read-only Filesystems - Critical directories are read-only where possible
  • Minimal Images - Use Alpine Linux base images (smaller attack surface)
  • Secret Management - Never hardcode secrets; use environment variables or secret managers

Performance

  • Layer Caching - Dockerfile layers are ordered for optimal caching
  • Dependency Caching - Package installations happen before code changes
  • Turbo Pruning - Only necessary dependencies are included in images
  • Image Size - Multi-stage builds keep production images minimal

Reliability

  • Health Checks - All services have health checks to verify readiness
  • Depends On - Proper service dependencies ensure correct startup order
  • Volume Management - Persistent data stored in named volumes
  • Restart Policy - Services automatically restart on failure

Common Docker Commands

Build Images

# Build all images
docker-compose -f docker-compose.prod.yml build

# Build with no cache (fresh build)
docker-compose -f docker-compose.prod.yml build --no-cache

Run Services

# Start all services
docker-compose -f docker-compose.prod.yml up

# Start all services in background (detached mode)
docker-compose -f docker-compose.prod.yml up -d

# Start specific service
docker-compose -f docker-compose.prod.yml up api

Monitor & Debug

# View logs
docker-compose -f docker-compose.prod.yml logs

# Follow logs
docker-compose -f docker-compose.prod.yml logs -f

# Logs for specific service
docker-compose -f docker-compose.prod.yml logs -f api

# View running containers
docker-compose -f docker-compose.prod.yml ps

# Execute command in container
docker-compose -f docker-compose.prod.yml exec api sh

Stop & Cleanup

# Stop all services
docker-compose -f docker-compose.prod.yml stop

# Stop and remove containers (keeps volumes)
docker-compose -f docker-compose.prod.yml down

# Remove everything including volumes (destructive)
docker-compose -f docker-compose.prod.yml down -v

# Remove unused images
docker image prune

Troubleshooting

Container Fails to Start

# Check logs
docker-compose -f docker-compose.prod.yml logs web

# Check health status
docker-compose -f docker-compose.prod.yml ps

# Restart service
docker-compose -f docker-compose.prod.yml restart web

Database Connection Issues

# Check if PostgreSQL is healthy
docker-compose -f docker-compose.prod.yml ps postgres

# Connect to database
docker-compose -f docker-compose.prod.yml exec postgres psql -U postgres -d build-elevate

# View PostgreSQL logs
docker-compose -f docker-compose.prod.yml logs postgres

Clear Docker Resources

# Remove stopped containers
docker container prune

# Remove unused images
docker image prune

# Remove all unused resources (images, containers, volumes)
docker system prune -a

For the complete docker-compose.prod.yml configuration, refer to the file in your repository root.

Next Steps

  • Deploy with Docker - Use Docker Compose on your server or cloud provider
  • Verify Services - Run docker-compose -f docker-compose.prod.yml ps to check all services are healthy
  • View Logs - Use docker-compose -f docker-compose.prod.yml logs to monitor application behavior
  • Scale Services - Use Docker Compose replicas to run multiple instances (advanced)

For deployment guides, see the Deployment Documentation. To configure environment variables for containers, see Environment Variables.

On this page