AppsContainer ManagementDocker Compose Anywhere

Docker Compose Anywhere

Effortlessly deploy Docker Compose apps in production with zero downtime using an opinionated template 🛠️.

Directory Structure

    • .env
    • docker-compose.yml

docker-compose.yml

version: "3.9"
 
services:
  traefik:
    image: traefik:v3.1.2
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=${ACME_EMAIL:-your@email.com}"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
    networks:
      - net
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`${TRAEFIK_DASHBOARD_DOMAIN:-traefik.localhost}`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.middlewares=auth"
      - "traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_DASHBOARD_AUTH:-admin:$$apr1$$salt$$hashedpassword}"
      - "traefik.http.routers.dashboard.tls=${USE_SSL:-false}"
      - "traefik.http.routers.dashboard.tls.certresolver=myresolver"
 
  redis:
    image: redis
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - net
    restart: always    
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "6"
 
  db:
    image: ankane/pgvector
    container_name: postgres_db
    ports:
      - "5433:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=${POSTGRES_USER:-postgres}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres}
      - POSTGRES_DB=${POSTGRES_DB:-postgres}
      - POSTGRES_HOST_AUTH_METHOD=trust
    networks:
      - net
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-postgres}"]
      interval: 10s
      timeout: 5s
      retries: 5
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "6"
 
 
  api:
    image: ghcr.io/hadijaveed/docker-compose-anywhere/app:latest
    depends_on:
      - traefik
      - db
      - redis
      - dozzle
    env_file:
      - .env
    environment:
      - DATABASE_URL=postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db:5432/${POSTGRES_DB:-postgres}
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    networks:
      - net
    deploy:
      replicas: ${APP_REPLICAS:-2}
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`${API_DOMAIN:-api.localhost}`)"
      - "traefik.http.routers.app.tls=${USE_SSL:-false}"
      - "traefik.http.routers.app.tls.certresolver=myresolver"
      - "traefik.http.services.app.loadbalancer.server.port=8000"
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "6"
 
  background:
    image: ghcr.io/hadijaveed/docker-compose-anywhere/background:latest
    depends_on:
      - db
      - redis
    environment:
      - DATABASE_URL=postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db:5432/${POSTGRES_DB:-postgres}
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    networks:
      - net
    deploy:
      replicas: ${BACKGROUND_REPLICAS:-2}
    restart: always
    env_file:
      - .env
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "6"
 
  web:
    image: ghcr.io/hadijaveed/docker-compose-anywhere/web:latest
    depends_on:
      - api
    networks:
      - net
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.web.rule=Host(`${WEB_DOMAIN:-app.localhost}`)"
      - "traefik.http.routers.web.tls=${USE_SSL:-false}"
      - "traefik.http.routers.web.tls.certresolver=myresolver"
      - "traefik.http.services.web.loadbalancer.server.port=3001"
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "6"
 
  dozzle:
    image: amir20/dozzle:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./dozzle/data:/data
    networks:
      - net
    environment:
      DOZZLE_NO_ANALYTICS: true
      DOZZLE_AUTH_PROVIDER: simple
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dozzle.rule=Host(`${DOZZLE_DOMAIN:-dozzle.localhost}`)"
      - "traefik.http.routers.dozzle.tls=${USE_SSL:-false}"
      - "traefik.http.routers.dozzle.tls.certresolver=myresolver"
      - "traefik.http.services.dozzle.loadbalancer.server.port=8080"
    healthcheck:
      test: ["CMD", "/dozzle", "healthcheck"]
      interval: 3s
      timeout: 30s
      retries: 5
      start_period: 30s
 
volumes:
  postgres_data:
  redis_data:
 
networks:
  net:
    driver: bridge

Resources

GitHub: https://github.com/hadijaveed/docker-compose-anywhere

GitHub Container Registry: ghcr.io/hadijaveed/docker-compose-anywhere/web

Configuration: https://github.com/hadijaveed/docker-compose-anywhere/blob/main/docker-compose-deploy.yml