Ctrl K
ComunidadGuías…

docker-compose.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
x-default-logging: &default-logging
  driver: json-file
  options:
    max-size: "10m"
    max-file: "5"

services:
  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      app:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped
    logging: *default-logging
    networks:
      - edge
      - backend

  app:
    image: remind-app:latest
    build:
      context: .
      dockerfile: Dockerfile
    expose:
      - "5000"
    env_file:
      - path: .env
        required: false
    environment:
      - FLASK_ENV=production
      - FLASK_DEBUG=0
      - SECRET_KEY=${SECRET_KEY:?Set SECRET_KEY}
      - SECRET_ROTATION_EPOCH=${SECRET_ROTATION_EPOCH:-0}
      - AI_PROVIDER_API_KEY=${AI_PROVIDER_API_KEY:?Set AI_PROVIDER_API_KEY}
      - AI_PROVIDER_MODEL_NAME=${AI_PROVIDER_MODEL_NAME:?Set AI_PROVIDER_MODEL_NAME}
      - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
      - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
      - TELEGRAM_CLIENT_ID=${TELEGRAM_CLIENT_ID:-}
      - TURNSTILE_SITE_KEY=${TURNSTILE_SITE_KEY:-}
      - TURNSTILE_SECRET_KEY=${TURNSTILE_SECRET_KEY:-}
      - BACKEND_URL=${BACKEND_URL:?Set BACKEND_URL}
      - ALLOWED_HOSTS=${ALLOWED_HOSTS:-},${TUNNEL_HOST:-}
      - CORS_ORIGINS=${CORS_ORIGINS:-},${TUNNEL_ORIGIN:-}
      - DB_PASSWORD=${DB_PASSWORD:?Set DB_PASSWORD}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Set REDIS_PASSWORD}
      - DATABASE_URL=postgresql://remind:${DB_PASSWORD:?Set DB_PASSWORD}@db:5432/remind_db
      - REDIS_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/0
      - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - EMAIL_SENDER=${EMAIL_SENDER:?Set EMAIL_SENDER}
      - EMAIL_PASSWORD=${EMAIL_PASSWORD:?Set EMAIL_PASSWORD}
      - GITHUB_APP_ID=${GITHUB_APP_ID:?Set GITHUB_APP_ID}
      - GITHUB_APP_CLIENT_ID=${GITHUB_APP_CLIENT_ID:?Set GITHUB_APP_CLIENT_ID}
      - GITHUB_APP_CLIENT_SECRET=${GITHUB_APP_CLIENT_SECRET:?Set GITHUB_APP_CLIENT_SECRET}
      - GITHUB_APP_SLUG=${GITHUB_APP_SLUG:?Set GITHUB_APP_SLUG}
      - GITHUB_PUBLIC_BASE_URL=${GITHUB_PUBLIC_BASE_URL:?Set GITHUB_PUBLIC_BASE_URL}
      - GITHUB_OAUTH_ENCRYPTION_KEY=${GITHUB_OAUTH_ENCRYPTION_KEY:-}
      - LOCALHOST_MODE=False
      - CORS_ALLOW_LOCAL_ORIGINS=False
      - ALLOW_CROSS_SUBDOMAIN_SESSION_COOKIE=False
      - PUBLIC_METRICS_ENABLED=False
      - PUBLIC_OPENAPI_ENABLED=False
      - ALLOW_GUEST_CHATS_SAVE=False
      - ENABLE_STRICT_HTTPS=False
      - VALIDATE_USER_AGENT=True
      - PYTHON_RUNNER_ENABLED=True
      - PYTHON_RUNNER_QUEUE=/var/lib/remind-python-runner
    volumes:
      - ./database:/app/database
      - ./logs:/app/logs
      - python_runner_queue:/var/lib/remind-python-runner
    depends_on:
      redis:
        condition: service_healthy
      db:
        condition: service_healthy
      init-storage:
        condition: service_completed_successfully
      init-python-runner-storage:
        condition: service_completed_successfully
      migrate:
        condition: service_completed_successfully
    restart: unless-stopped
    logging: *default-logging
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          cpus: '0.80'
          memory: 2G
        reservations:
          cpus: '0.25'
          memory: 512M
    networks:
      - backend
      - edge

  telegram-bot:
    image: remind-app:latest
    command: python telegram_bot.py
    profiles: ["telegram"]
    env_file:
      - path: .env
        required: false
    environment:
      - FLASK_ENV=production
      - FLASK_DEBUG=0
      - SECRET_KEY=${SECRET_KEY:?Set SECRET_KEY}
      - SECRET_ROTATION_EPOCH=${SECRET_ROTATION_EPOCH:-0}
      - AI_PROVIDER_API_KEY=${AI_PROVIDER_API_KEY:?Set AI_PROVIDER_API_KEY}
      - AI_PROVIDER_MODEL_NAME=${AI_PROVIDER_MODEL_NAME:?Set AI_PROVIDER_MODEL_NAME}
      - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
      - TELEGRAM_BOT_USERNAME=${TELEGRAM_BOT_USERNAME:-}
      - TELEGRAM_BOT_API_BASE=${TELEGRAM_BOT_API_BASE:-https://api.telegram.org}
      - TELEGRAM_DRAFT_INTERVAL_SECONDS=${TELEGRAM_DRAFT_INTERVAL_SECONDS:-0.55}
      - TELEGRAM_MAX_CONTEXT_MESSAGES=${TELEGRAM_MAX_CONTEXT_MESSAGES:-4}
      - TELEGRAM_MAX_CONTEXT_MESSAGES_INLINE=${TELEGRAM_MAX_CONTEXT_MESSAGES_INLINE:-4}
      - TELEGRAM_THINKING_LEVEL=${TELEGRAM_THINKING_LEVEL:-low}
      - TELEGRAM_THINKING_LEVEL_MESSAGE=${TELEGRAM_THINKING_LEVEL_MESSAGE:-medium}
      - TELEGRAM_THINKING_LEVEL_INLINE=${TELEGRAM_THINKING_LEVEL_INLINE:-}
      - BACKEND_URL=${BACKEND_URL:?Set BACKEND_URL}
      - DB_PASSWORD=${DB_PASSWORD:?Set DB_PASSWORD}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Set REDIS_PASSWORD}
      - DATABASE_URL=postgresql://remind:${DB_PASSWORD:?Set DB_PASSWORD}@db:5432/remind_db
      - REDIS_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/0
      - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - ENABLE_STRICT_HTTPS=False
      - ALLOW_CROSS_SUBDOMAIN_SESSION_COOKIE=False
      - PUBLIC_METRICS_ENABLED=False
      - PUBLIC_OPENAPI_ENABLED=False
    volumes:
      - ./database:/app/database
      - ./logs:/app/logs
    depends_on:
      redis:
        condition: service_healthy
      db:
        condition: service_healthy
      init-storage:
        condition: service_completed_successfully
      migrate:
        condition: service_completed_successfully
    healthcheck:
      disable: true
    restart: unless-stopped
    logging: *default-logging
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          cpus: '0.80'
          memory: 2G
    networks:
      - backend
      - edge

  cloudflared:
    image: cloudflare/cloudflared:latest
    command: tunnel --no-autoupdate --url http://nginx:80
    profiles: ["tunnel"]
    depends_on:
      nginx:
        condition: service_healthy
    restart: unless-stopped
    logging: *default-logging
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    networks:
      - edge

  worker:
    image: remind-app:latest
    command: celery -A celery_worker.celery worker --loglevel=info --concurrency=2
    env_file:
      - path: .env
        required: false
    environment:
      - FLASK_ENV=production
      - FLASK_DEBUG=0
      - SECRET_KEY=${SECRET_KEY:?Set SECRET_KEY}
      - SECRET_ROTATION_EPOCH=${SECRET_ROTATION_EPOCH:-0}
      - AI_PROVIDER_API_KEY=${AI_PROVIDER_API_KEY:?Set AI_PROVIDER_API_KEY}
      - AI_PROVIDER_MODEL_NAME=${AI_PROVIDER_MODEL_NAME:?Set AI_PROVIDER_MODEL_NAME}
      - DB_PASSWORD=${DB_PASSWORD:?Set DB_PASSWORD}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Set REDIS_PASSWORD}
      - DATABASE_URL=postgresql://remind:${DB_PASSWORD:?Set DB_PASSWORD}@db:5432/remind_db
      - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - REDIS_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/0
      - ENABLE_STRICT_HTTPS=False
      - ALLOW_CROSS_SUBDOMAIN_SESSION_COOKIE=False
      - PUBLIC_METRICS_ENABLED=False
      - PUBLIC_OPENAPI_ENABLED=False
      - PYTHON_RUNNER_ENABLED=True
      - PYTHON_RUNNER_QUEUE=/var/lib/remind-python-runner
    volumes:
      - ./database:/app/database
      - ./logs:/app/logs
      - python_runner_queue:/var/lib/remind-python-runner
    depends_on:
      redis:
        condition: service_healthy
      db:
        condition: service_healthy
      init-storage:
        condition: service_completed_successfully
      init-python-runner-storage:
        condition: service_completed_successfully
      migrate:
        condition: service_completed_successfully
    healthcheck:
      disable: true
    restart: unless-stopped
    logging: *default-logging
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          cpus: '0.80'
          memory: 2G
    networks:
      - backend
      - edge

  init-storage:
    image: remind-app:latest
    user: "0:0"
    command:
      - sh
      - -c
      - chown -R 1001:1001 /app/database /app/logs && chmod -R u+rwX,go-rwx /app/database /app/logs
    volumes:
      - ./database:/app/database
      - ./logs:/app/logs
    restart: "no"
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - FOWNER
    security_opt:
      - no-new-privileges:true
    logging: *default-logging

  init-python-runner-storage:
    image: remind-python-runner:latest
    build:
      context: .
      dockerfile: Dockerfile.python-runner
    user: "0:0"
    command:
      - sh
      - -c
      - chown 0:0 /jobs && chmod 700 /jobs && mkdir -p /jobs/requests /jobs/responses && chown -R 1001:0 /jobs && chmod 2770 /jobs /jobs/requests /jobs/responses
    volumes:
      - python_runner_queue:/jobs
    network_mode: none
    restart: "no"
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - FOWNER
    security_opt:
      - no-new-privileges:true
    logging: *default-logging

  python-runner:
    image: remind-python-runner:latest
    build:
      context: .
      dockerfile: Dockerfile.python-runner
    environment:
      - PYTHON_RUNNER_QUEUE=/jobs
    volumes:
      - python_runner_queue:/jobs
    depends_on:
      init-python-runner-storage:
        condition: service_completed_successfully
    network_mode: none
    read_only: true
    tmpfs:
      - /tmp:rw,noexec,nosuid,nodev,size=640m,mode=0711
      - /dev/shm:rw,noexec,nosuid,nodev,size=1m,mode=000
    user: "0:0"
    cap_drop:
      - ALL
    cap_add:
      - SETUID
      - SETGID
      - KILL
      - CHOWN
      - DAC_OVERRIDE
    security_opt:
      - no-new-privileges:true
    pids_limit: 64
    mem_limit: 768m
    cpus: 0.75
    ulimits:
      nofile:
        soft: 128
        hard: 128
      nproc:
        soft: 64
        hard: 64
    restart: unless-stopped
    stop_grace_period: 5s
    logging: *default-logging

  migrate:
    image: remind-app:latest
    command: python -m scripts.prepare_database
    env_file:
      - path: .env
        required: false
    environment:
      - FLASK_ENV=production
      - FLASK_DEBUG=0
      - SECRET_KEY=${SECRET_KEY:?Set SECRET_KEY}
      - AI_PROVIDER_API_KEY=${AI_PROVIDER_API_KEY:?Set AI_PROVIDER_API_KEY}
      - AI_PROVIDER_MODEL_NAME=${AI_PROVIDER_MODEL_NAME:?Set AI_PROVIDER_MODEL_NAME}
      - BACKEND_URL=${BACKEND_URL:?Set BACKEND_URL}
      - DB_PASSWORD=${DB_PASSWORD:?Set DB_PASSWORD}
      - REDIS_PASSWORD=${REDIS_PASSWORD:?Set REDIS_PASSWORD}
      - DATABASE_URL=postgresql://remind:${DB_PASSWORD:?Set DB_PASSWORD}@db:5432/remind_db
      - REDIS_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/0
      - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD}@redis:6379/1
      - EMAIL_SENDER=${EMAIL_SENDER:?Set EMAIL_SENDER}
      - EMAIL_PASSWORD=${EMAIL_PASSWORD:?Set EMAIL_PASSWORD}
      - LOCALHOST_MODE=False
      - CORS_ALLOW_LOCAL_ORIGINS=False
      - ALLOW_CROSS_SUBDOMAIN_SESSION_COOKIE=False
      - ENABLE_STRICT_HTTPS=False
    volumes:
      - ./database:/app/database
      - ./logs:/app/logs
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
      init-storage:
        condition: service_completed_successfully
    restart: "no"
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    networks:
      - backend
    logging: *default-logging

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: remind
      POSTGRES_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD}
      POSTGRES_DB: remind_db
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U remind -d remind_db"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    logging: *default-logging
    networks:
      - backend

  redis:
    image: redis:7-alpine
    environment:
      - REDISCLI_AUTH=${REDIS_PASSWORD:?Set REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    restart: unless-stopped
    command:
      - redis-server
      - --appendonly
      - "yes"
      - --maxmemory
      - 256mb
      - --maxmemory-policy
      - allkeys-lru
      - --protected-mode
      - "yes"
      - --bind
      - 0.0.0.0
      - --requirepass
      - ${REDIS_PASSWORD:?Set REDIS_PASSWORD}
      - --rename-command
      - CONFIG
      - ""
      - --rename-command
      - FLUSHALL
      - ""
      - --rename-command
      - FLUSHDB
      - ""
      - --rename-command
      - SHUTDOWN
      - ""
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 15s
    logging: *default-logging
    networks:
      - backend

volumes:
  postgres_data:
  redis_data:
  python_runner_queue:

networks:
  edge:
  backend:
    internal: true