RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /Courses
  5. /Capstone: Full-Stack AI App
  6. /Ch. 10
Capstone: Full-Stack AI App

10. Docker Compose Deployment

Chapter 10 of 18 · 15 min
KEY INSIGHT

Docker Compose is configuration as code—treat the compose file like production infrastructure and version it accordingly.

Docker Compose orchestrates multi-container deployments for development and staging. Production typically uses Kubernetes, but Docker Compose provides a simpler path for smaller deployments. The compose file defines services, networks, volumes, and dependencies.

# docker-compose.yml
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: aiapp
      POSTGRES_USER: aiapp
      POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    secrets:
      - postgres_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U aiapp"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      model_server:
        condition: service_healthy
    environment:
      DATABASE_URL: postgresql://aiapp@postgres/aiapp
      REDIS_URL: redis://redis:6379
      MODEL_SERVER_URL: http://model_server:8080
      SECRET_KEY_FILE: /run/secrets/secret_key
    secrets:
      - postgres_password
      - secret_key
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 512M

  model_server:
    build:
      context: ./model-server
      dockerfile: Dockerfile
    environment:
      MODEL_PATH: /models/mistral-7b.q4_k_m.gguf
      CONTEXT_SIZE: 4096
    volumes:
      - model_cache:/models
    deploy:
      resources:
        limits:
          memory: 8G
        reservations:
          devices:
            - capabilities: [gpu]

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    depends_on:
      - backend

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/certs:/etc/nginx/certs:ro
    depends_on:
      - backend
      - frontend

volumes:
  postgres_data:
  redis_data:
  model_cache:

secrets:
  postgres_password:
    file: ./secrets/postgres_password.txt
  secret_key:
    file: ./secrets/secret_key.txt

Resource limits prevent any service from consuming all host memory. The memory reservation tells Docker to pre-allocate memory for the container, improving performance. The GPU reservation requires the Docker runtime to have GPU access configured.

Secrets management requires secure file permissions. Secrets files should have 0600 permissions:

# Create secrets directory with restricted access
mkdir -p secrets
chmod 700 secrets
echo "your-secure-password" > secrets/postgres_password.txt
chmod 600 secrets/postgres_password.txt

Common Docker Compose failures include port conflicts when services try to bind to ports already in use. Check with netstat -tulpn | grep LISTEN. Volume permission issues when UIDs mismatch between host and container—use named volumes instead of bind mounts to avoid this.

EXERCISE

Create a Docker Compose file that starts the full stack with health checks and resource limits. Verify all services start successfully and communicate.

← Chapter 9
Security Audit
Chapter 11 →
CI/CD Pipeline