version: '3.9' services: # ════════════════════════════════════════════════════════════════ # PostgreSQL Database # ════════════════════════════════════════════════════════════════ postgres: image: postgres:15-alpine container_name: tg_autoposter_postgres environment: POSTGRES_USER: ${DB_USER:-autoposter} POSTGRES_PASSWORD: ${DB_PASSWORD:-autoposter_password} POSTGRES_DB: ${DB_NAME:-autoposter_db} POSTGRES_INITDB_ARGS: "--encoding=UTF8" ports: - "${DB_PORT:-5432}:5432" volumes: - postgres_data:/var/lib/postgresql/data networks: - autoposter_network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-autoposter} -d ${DB_NAME:-autoposter_db}"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Redis Cache & Celery Broker # ════════════════════════════════════════════════════════════════ redis: image: redis:7-alpine container_name: tg_autoposter_redis ports: - "${REDIS_PORT:-6379}:6379" command: redis-server --appendonly yes ${REDIS_PASSWORD:+--requirepass ${REDIS_PASSWORD}} volumes: - redis_data:/data networks: - autoposter_network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Main Bot Service # ════════════════════════════════════════════════════════════════ bot: build: context: . dockerfile: Dockerfile container_name: tg_autoposter_bot environment: # Telegram TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} TELEGRAM_TIMEOUT: ${TELEGRAM_TIMEOUT:-30} # Telethon Client USE_TELETHON: ${USE_TELETHON:-false} TELETHON_API_ID: ${TELETHON_API_ID} TELETHON_API_HASH: ${TELETHON_API_HASH} TELETHON_PHONE: ${TELETHON_PHONE} TELETHON_FLOOD_WAIT_MAX: ${TELETHON_FLOOD_WAIT_MAX:-60} # Database (PostgreSQL) DATABASE_URL: postgresql+asyncpg://${DB_USER:-autoposter}:${DB_PASSWORD:-autoposter_password}@postgres:5432/${DB_NAME:-autoposter_db} # Redis & Celery REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_DB: ${REDIS_DB:-0} REDIS_PASSWORD: ${REDIS_PASSWORD:-} # Logging LOG_LEVEL: ${LOG_LEVEL:-INFO} # Bot Settings MAX_RETRIES: ${MAX_RETRIES:-3} RETRY_DELAY: ${RETRY_DELAY:-5} MIN_SEND_INTERVAL: ${MIN_SEND_INTERVAL:-0.5} # Parsing ENABLE_KEYWORD_PARSING: ${ENABLE_KEYWORD_PARSING:-true} GROUP_PARSE_INTERVAL: ${GROUP_PARSE_INTERVAL:-3600} MAX_MEMBERS_TO_LOAD: ${MAX_MEMBERS_TO_LOAD:-1000} # Statistics ENABLE_STATISTICS: ${ENABLE_STATISTICS:-true} MESSAGE_HISTORY_DAYS: ${MESSAGE_HISTORY_DAYS:-30} volumes: - ./app:/app/app - ./logs:/app/logs - ./sessions:/app/sessions ports: - "8000:8000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - autoposter_network command: python -m app restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Celery Worker (для отправки сообщений) # ════════════════════════════════════════════════════════════════ celery_worker_send: build: context: . dockerfile: Dockerfile container_name: tg_autoposter_celery_send environment: TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} USE_TELETHON: ${USE_TELETHON:-false} TELETHON_API_ID: ${TELETHON_API_ID} TELETHON_API_HASH: ${TELETHON_API_HASH} TELETHON_PHONE: ${TELETHON_PHONE} DATABASE_URL: postgresql+asyncpg://${DB_USER:-autoposter}:${DB_PASSWORD:-autoposter_password}@postgres:5432/${DB_NAME:-autoposter_db} REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_DB: ${REDIS_DB:-0} REDIS_PASSWORD: ${REDIS_PASSWORD:-} LOG_LEVEL: ${LOG_LEVEL:-INFO} volumes: - ./app:/app/app - ./logs:/app/logs - ./sessions:/app/sessions depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - autoposter_network command: celery -A app.celery_config worker --loglevel=info --queues=messages -c 4 restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Celery Worker (для парсинга групп) # ════════════════════════════════════════════════════════════════ celery_worker_parse: build: context: . dockerfile: Dockerfile container_name: tg_autoposter_celery_parse environment: TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} USE_TELETHON: ${USE_TELETHON:-false} TELETHON_API_ID: ${TELETHON_API_ID} TELETHON_API_HASH: ${TELETHON_API_HASH} TELETHON_PHONE: ${TELETHON_PHONE} DATABASE_URL: postgresql+asyncpg://${DB_USER:-autoposter}:${DB_PASSWORD:-autoposter_password}@postgres:5432/${DB_NAME:-autoposter_db} REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_DB: ${REDIS_DB:-0} REDIS_PASSWORD: ${REDIS_PASSWORD:-} LOG_LEVEL: ${LOG_LEVEL:-INFO} volumes: - ./app:/app/app - ./logs:/app/logs - ./sessions:/app/sessions depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - autoposter_network command: celery -A app.celery_config worker --loglevel=info --queues=parsing -c 2 restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Celery Worker (для обслуживания) # ════════════════════════════════════════════════════════════════ celery_worker_maintenance: build: context: . dockerfile: Dockerfile container_name: tg_autoposter_celery_maintenance environment: TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} DATABASE_URL: postgresql+asyncpg://${DB_USER:-autoposter}:${DB_PASSWORD:-autoposter_password}@postgres:5432/${DB_NAME:-autoposter_db} REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_DB: ${REDIS_DB:-0} REDIS_PASSWORD: ${REDIS_PASSWORD:-} LOG_LEVEL: ${LOG_LEVEL:-INFO} volumes: - ./app:/app/app - ./logs:/app/logs depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - autoposter_network command: celery -A app.celery_config worker --loglevel=info --queues=maintenance -c 1 restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Celery Beat (Планировщик) # ════════════════════════════════════════════════════════════════ celery_beat: build: context: . dockerfile: Dockerfile container_name: tg_autoposter_celery_beat environment: TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} DATABASE_URL: postgresql+asyncpg://${DB_USER:-autoposter}:${DB_PASSWORD:-autoposter_password}@postgres:5432/${DB_NAME:-autoposter_db} REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_DB: ${REDIS_DB:-0} REDIS_PASSWORD: ${REDIS_PASSWORD:-} LOG_LEVEL: ${LOG_LEVEL:-INFO} volumes: - ./app:/app/app - ./logs:/app/logs depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - autoposter_network command: celery -A app.celery_config beat --loglevel=info restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Flower (Мониторинг Celery) # ════════════════════════════════════════════════════════════════ flower: image: mher/flower:2.0 container_name: tg_autoposter_flower environment: CELERY_BROKER_URL: redis://${REDIS_PASSWORD:+:${REDIS_PASSWORD}@}${REDIS_HOST:-redis}:${REDIS_PORT:-6379}/${REDIS_DB:-0} CELERY_RESULT_BACKEND: redis://${REDIS_PASSWORD:+:${REDIS_PASSWORD}@}${REDIS_HOST:-redis}:${REDIS_PORT:-6379}/$((${REDIS_DB:-0}+1)) FLOWER_PORT: 5555 ports: - "5555:5555" depends_on: redis: condition: service_healthy networks: - autoposter_network command: celery --broker=redis://${REDIS_PASSWORD:+:${REDIS_PASSWORD}@}${REDIS_HOST:-redis}:${REDIS_PORT:-6379}/${REDIS_DB:-0} flower --port=5555 restart: unless-stopped # ════════════════════════════════════════════════════════════════ # Telethon UserBot Microservice # ════════════════════════════════════════════════════════════════ userbot: build: context: . dockerfile: Dockerfile.userbot container_name: tg_autoposter_userbot environment: # Telethon Client USE_TELETHON: ${USE_TELETHON:-true} TELETHON_API_ID: ${TELETHON_API_ID} TELETHON_API_HASH: ${TELETHON_API_HASH} TELETHON_PHONE: ${TELETHON_PHONE} TELETHON_FLOOD_WAIT_MAX: ${TELETHON_FLOOD_WAIT_MAX:-60} # Database (PostgreSQL) DATABASE_URL: postgresql+asyncpg://${DB_USER:-autoposter}:${DB_PASSWORD:-autoposter_password}@postgres:5432/${DB_NAME:-autoposter_db} # Redis & Celery REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_DB: ${REDIS_DB:-0} REDIS_PASSWORD: ${REDIS_PASSWORD:-} # Logging LOG_LEVEL: ${LOG_LEVEL:-INFO} volumes: - ./app:/app/app - ./logs:/app/logs - ./sessions:/app/sessions depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - autoposter_network restart: unless-stopped volumes: postgres_data: driver: local redis_data: driver: local networks: autoposter_network: driver: bridge