version: '3.8' services: # PostgreSQL Database with optimizations postgres: image: postgres:15-alpine container_name: tg_autoposter_postgres_prod environment: POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: ${DB_NAME} POSTGRES_INITDB_ARGS: "-c shared_buffers=256MB -c max_connections=200 -c effective_cache_size=1GB" volumes: - postgres_data_prod:/var/lib/postgresql/data - ./backups:/backups ports: - "5432:5432" networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"] interval: 10s timeout: 5s retries: 10 start_period: 20s restart: always deploy: resources: limits: cpus: '2' memory: 1G reservations: cpus: '1' memory: 512M logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Redis Cache with persistence redis: image: redis:7-alpine container_name: tg_autoposter_redis_prod command: > redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes --appendfsync everysec --maxmemory 512mb --maxmemory-policy allkeys-lru volumes: - redis_data_prod:/data ports: - "6379:6379" networks: - backend healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 10 start_period: 20s restart: always deploy: resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Main Telegram Bot bot: image: ${DOCKER_USERNAME}/tg-autoposter:latest container_name: tg_autoposter_bot_prod build: context: . dockerfile: Dockerfile environment: - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - TELEGRAM_API_ID=${TELEGRAM_API_ID} - TELEGRAM_API_HASH=${TELEGRAM_API_HASH} - ADMIN_ID=${ADMIN_ID} - DB_HOST=postgres - DB_PORT=5432 - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_DB=0 - REDIS_PASSWORD=${REDIS_PASSWORD} - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND_URL=redis://:${REDIS_PASSWORD}@redis:6379/1 - LOG_LEVEL=INFO - DEBUG=False volumes: - ./logs:/app/logs - ./sessions:/app/sessions depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - backend restart: always deploy: resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Celery Worker - Message Queue (4 concurrent) celery_worker_send: image: ${DOCKER_USERNAME}/tg-autoposter:latest container_name: tg_autoposter_worker_send_prod build: context: . dockerfile: Dockerfile command: celery -A app.celery_config worker -Q messages -n worker_send@%h -c 4 -l info --max-tasks-per-child=500 --without-gossip --without-mingle --without-heartbeat environment: - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - TELEGRAM_API_ID=${TELEGRAM_API_ID} - TELEGRAM_API_HASH=${TELEGRAM_API_HASH} - ADMIN_ID=${ADMIN_ID} - DB_HOST=postgres - DB_PORT=5432 - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_DB=0 - REDIS_PASSWORD=${REDIS_PASSWORD} - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND_URL=redis://:${REDIS_PASSWORD}@redis:6379/1 - LOG_LEVEL=INFO volumes: - ./logs:/app/logs - ./sessions:/app/sessions depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - backend restart: always deploy: replicas: 2 resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M update_config: parallelism: 1 delay: 10s logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Celery Worker - Parsing Queue (2 concurrent) celery_worker_parse: image: ${DOCKER_USERNAME}/tg-autoposter:latest container_name: tg_autoposter_worker_parse_prod command: celery -A app.celery_config worker -Q parsing -n worker_parse@%h -c 2 -l info --max-tasks-per-child=100 --without-gossip --without-mingle --without-heartbeat environment: - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - TELEGRAM_API_ID=${TELEGRAM_API_ID} - TELEGRAM_API_HASH=${TELEGRAM_API_HASH} - ADMIN_ID=${ADMIN_ID} - DB_HOST=postgres - DB_PORT=5432 - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_DB=0 - REDIS_PASSWORD=${REDIS_PASSWORD} - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND_URL=redis://:${REDIS_PASSWORD}@redis:6379/1 - LOG_LEVEL=INFO volumes: - ./logs:/app/logs - ./sessions:/app/sessions depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - backend restart: always deploy: resources: limits: cpus: '0.5' memory: 256M reservations: cpus: '0.25' memory: 128M logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Celery Worker - Maintenance Queue (1 concurrent) celery_worker_maintenance: image: ${DOCKER_USERNAME}/tg-autoposter:latest container_name: tg_autoposter_worker_maintenance_prod command: celery -A app.celery_config worker -Q maintenance -n worker_maintenance@%h -c 1 -l info --max-tasks-per-child=50 --without-gossip --without-mingle --without-heartbeat environment: - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - TELEGRAM_API_ID=${TELEGRAM_API_ID} - TELEGRAM_API_HASH=${TELEGRAM_API_HASH} - ADMIN_ID=${ADMIN_ID} - DB_HOST=postgres - DB_PORT=5432 - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_DB=0 - REDIS_PASSWORD=${REDIS_PASSWORD} - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND_URL=redis://:${REDIS_PASSWORD}@redis:6379/1 - LOG_LEVEL=INFO volumes: - ./logs:/app/logs - ./sessions:/app/sessions depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - backend restart: always deploy: resources: limits: cpus: '0.5' memory: 256M reservations: cpus: '0.25' memory: 128M logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Celery Beat - Task Scheduler celery_beat: image: ${DOCKER_USERNAME}/tg-autoposter:latest container_name: tg_autoposter_beat_prod command: celery -A app.celery_config beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler environment: - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - TELEGRAM_API_ID=${TELEGRAM_API_ID} - TELEGRAM_API_HASH=${TELEGRAM_API_HASH} - ADMIN_ID=${ADMIN_ID} - DB_HOST=postgres - DB_PORT=5432 - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - DB_NAME=${DB_NAME} - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_DB=0 - REDIS_PASSWORD=${REDIS_PASSWORD} - CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@redis:6379/0 - CELERY_RESULT_BACKEND_URL=redis://:${REDIS_PASSWORD}@redis:6379/1 - LOG_LEVEL=INFO volumes: - ./logs:/app/logs depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - backend restart: always deploy: resources: limits: cpus: '0.5' memory: 256M reservations: cpus: '0.25' memory: 128M logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Flower - Celery Monitoring flower: image: mher/flower:2.0.1 container_name: tg_autoposter_flower_prod command: celery -A app.celery_config flower --port=5555 --basic_auth=admin:${FLOWER_PASSWORD} environment: CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/0 CELERY_RESULT_BACKEND: redis://:${REDIS_PASSWORD}@redis:6379/1 ports: - "5555:5555" depends_on: redis: condition: service_healthy networks: - backend restart: always deploy: resources: limits: cpus: '0.5' memory: 256M reservations: cpus: '0.25' memory: 128M logging: driver: "json-file" options: max-size: "100m" max-file: "10" # Optional: Prometheus for metrics collection prometheus: image: prom/prometheus:latest container_name: tg_autoposter_prometheus_prod command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus networks: - backend restart: always deploy: resources: limits: cpus: '1' memory: 512M volumes: postgres_data_prod: driver: local redis_data_prod: driver: local prometheus_data: driver: local networks: backend: driver: bridge driver_opts: com.docker.network.bridge.name: br_tg_autoposter ipam: config: - subnet: 172.20.0.0/16