docker-compose.yml
Rama main · réplica de lectura del repositorio original.
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