From 4800e8c37528e1ddebe8982fabec69836502ada3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Mon, 3 Nov 2025 14:20:48 +0300 Subject: [PATCH] feat: Add production Docker orchestration with monitoring Production Stack (7 services): - buh_bot: Main bot from registry (1 CPU, 1GB RAM) - nginx: Reverse proxy with rate limiting (10 req/s) - prometheus: Metrics collection (30d retention) - grafana: Monitoring dashboards (port 3000) - node_exporter: Host metrics (port 9100) - cadvisor: Container metrics (port 8080) - watchtower: Auto-updates (hourly check) Configuration: - docker-compose.prod.yml with 7-service stack - nginx.conf with SSL-ready config and healthchecks - prometheus.yml with scrape configs - grafana datasource and dashboard provisioning - .env.prod.example template - Custom network 172.20.0.0/16 - Persistent volumes in /var/lib/buh_bot - Log rotation: 50MB x 5 files --- .env.prod.example | 45 +++ docker-compose.prod.yml | 286 ++++++++++++++++++ monitoring/grafana/dashboards/dashboard.yml | 12 + monitoring/grafana/datasources/prometheus.yml | 11 + monitoring/prometheus.yml | 47 +++ nginx/nginx.conf | 87 ++++++ 6 files changed, 488 insertions(+) create mode 100644 .env.prod.example create mode 100644 docker-compose.prod.yml create mode 100644 monitoring/grafana/dashboards/dashboard.yml create mode 100644 monitoring/grafana/datasources/prometheus.yml create mode 100644 monitoring/prometheus.yml create mode 100644 nginx/nginx.conf diff --git a/.env.prod.example b/.env.prod.example new file mode 100644 index 0000000..9b8717b --- /dev/null +++ b/.env.prod.example @@ -0,0 +1,45 @@ +# Production Environment Variables + +# ===== Основные настройки ===== +# Telegram Bot Token (обязательно!) +TELEGRAM_BOT_TOKEN=your_production_bot_token_here + +# МойСклад API +MOYSKLAD_API_URL=https://api.moysklad.ru/api/remap/1.2 + +# Timezone +TZ=Europe/Moscow + +# Уровень логирования (DEBUG, INFO, WARNING, ERROR) +LOG_LEVEL=INFO + +# ===== Docker Registry ===== +# Для использования собственного registry +DOCKER_REGISTRY=ghcr.io +DOCKER_USERNAME=your_github_username +BOT_VERSION=latest + +# ===== Nginx ===== +NGINX_HTTP_PORT=80 +NGINX_HTTPS_PORT=443 + +# ===== Мониторинг ===== +# Prometheus +PROMETHEUS_PORT=9090 + +# Grafana +GRAFANA_PORT=3000 +GRAFANA_USER=admin +GRAFANA_PASSWORD=change_me_in_production + +# ===== Watchtower (auto-update) ===== +# Уведомления (опционально) +# Примеры: +# Telegram: telegram://token@telegram?channels=channel_id +# Email: smtp://username:password@host:port/?from=sender@example.com&to=receiver@example.com +WATCHTOWER_NOTIFICATION_URL= + +# ===== Backup ===== +BACKUP_ENABLED=true +BACKUP_SCHEDULE=0 2 * * * +BACKUP_RETENTION_DAYS=30 diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..c84c629 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,286 @@ +version: '3.8' + +# Production Docker Compose для BUH Bot +# Использует готовые образы, nginx, мониторинг + +services: + # Telegram бот + buh_bot: + image: ${DOCKER_REGISTRY:-ghcr.io}/${DOCKER_USERNAME:-username}/buh_bot:${BOT_VERSION:-latest} + container_name: buh_bot_prod + restart: always + + environment: + - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} + - MOYSKLAD_API_URL=${MOYSKLAD_API_URL:-https://api.moysklad.ru/api/remap/1.2} + - TZ=${TZ:-Europe/Moscow} + - LOG_LEVEL=${LOG_LEVEL:-INFO} + - DATA_DIR=/app/data + - LOGS_DIR=/app/logs + + volumes: + # Персистентные данные на хосте + - /var/lib/buh_bot/data:/app/data + - /var/log/buh_bot:/app/logs + - /var/tmp/buh_bot:/app/temp_documents + + networks: + - buh_network + + # Ограничения ресурсов для production + deploy: + resources: + limits: + cpus: '1.0' + memory: 1G + reservations: + cpus: '0.5' + memory: 512M + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + + # Healthcheck для мониторинга + healthcheck: + test: ["CMD", "python", "-c", "import sys; sys.exit(0)"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Логирование с ротацией + logging: + driver: "json-file" + options: + max-size: "50m" + max-file: "5" + labels: "service=buh_bot,environment=production" + + labels: + - "com.buh_bot.service=telegram-bot" + - "com.buh_bot.environment=production" + + # Nginx reverse proxy (для webhook режима или API) + nginx: + image: nginx:alpine + container_name: buh_bot_nginx + restart: always + + ports: + - "${NGINX_HTTP_PORT:-80}:80" + - "${NGINX_HTTPS_PORT:-443}:443" + + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/ssl:/etc/nginx/ssl:ro + - /var/log/nginx:/var/log/nginx + + networks: + - buh_network + + depends_on: + - buh_bot + + deploy: + resources: + limits: + cpus: '0.5' + memory: 256M + + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"] + interval: 30s + timeout: 5s + retries: 3 + + logging: + driver: "json-file" + options: + max-size: "20m" + max-file: "3" + + # Prometheus для метрик + prometheus: + image: prom/prometheus:latest + container_name: buh_bot_prometheus + restart: always + + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--storage.tsdb.retention.time=30d' + + volumes: + - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro + - prometheus_data:/prometheus + + networks: + - buh_network + + ports: + - "${PROMETHEUS_PORT:-9090}:9090" + + deploy: + resources: + limits: + cpus: '0.5' + memory: 512M + + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # Grafana для визуализации метрик + grafana: + image: grafana/grafana:latest + container_name: buh_bot_grafana + restart: always + + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_USER:-admin} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin} + - GF_INSTALL_PLUGINS= + + volumes: + - grafana_data:/var/lib/grafana + - ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards:ro + - ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources:ro + + networks: + - buh_network + + ports: + - "${GRAFANA_PORT:-3000}:3000" + + depends_on: + - prometheus + + deploy: + resources: + limits: + cpus: '0.5' + memory: 512M + + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + # Node Exporter для метрик хоста + node_exporter: + image: prom/node-exporter:latest + container_name: buh_bot_node_exporter + restart: always + + command: + - '--path.procfs=/host/proc' + - '--path.sysfs=/host/sys' + - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)' + + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + + networks: + - buh_network + + ports: + - "9100:9100" + + deploy: + resources: + limits: + cpus: '0.2' + memory: 128M + + logging: + driver: "json-file" + options: + max-size: "5m" + max-file: "2" + + # cAdvisor для метрик контейнеров + cadvisor: + image: gcr.io/cadvisor/cadvisor:latest + container_name: buh_bot_cadvisor + restart: always + + privileged: true + + volumes: + - /:/rootfs:ro + - /var/run:/var/run:ro + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /dev/disk/:/dev/disk:ro + + networks: + - buh_network + + ports: + - "8080:8080" + + deploy: + resources: + limits: + cpus: '0.3' + memory: 256M + + logging: + driver: "json-file" + options: + max-size: "5m" + max-file: "2" + + # Watchtower для автоматического обновления образов + watchtower: + image: containrrr/watchtower:latest + container_name: buh_bot_watchtower + restart: always + + environment: + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_POLL_INTERVAL=3600 + - WATCHTOWER_INCLUDE_STOPPED=false + - WATCHTOWER_REVIVE_STOPPED=false + - WATCHTOWER_NOTIFICATIONS=shoutrrr + - WATCHTOWER_NOTIFICATION_URL=${WATCHTOWER_NOTIFICATION_URL:-} + + volumes: + - /var/run/docker.sock:/var/run/docker.sock + + networks: + - buh_network + + deploy: + resources: + limits: + cpus: '0.2' + memory: 128M + + logging: + driver: "json-file" + options: + max-size: "5m" + max-file: "2" + +# Сети +networks: + buh_network: + driver: bridge + ipam: + config: + - subnet: 172.20.0.0/16 + +# Volumes для персистентных данных +volumes: + prometheus_data: + driver: local + grafana_data: + driver: local diff --git a/monitoring/grafana/dashboards/dashboard.yml b/monitoring/grafana/dashboards/dashboard.yml new file mode 100644 index 0000000..1444589 --- /dev/null +++ b/monitoring/grafana/dashboards/dashboard.yml @@ -0,0 +1,12 @@ +apiVersion: 1 + +providers: + - name: 'BUH Bot Dashboards' + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + allowUiUpdates: true + options: + path: /etc/grafana/provisioning/dashboards diff --git a/monitoring/grafana/datasources/prometheus.yml b/monitoring/grafana/datasources/prometheus.yml new file mode 100644 index 0000000..63f693a --- /dev/null +++ b/monitoring/grafana/datasources/prometheus.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: true + jsonData: + timeInterval: "15s" diff --git a/monitoring/prometheus.yml b/monitoring/prometheus.yml new file mode 100644 index 0000000..2f979ae --- /dev/null +++ b/monitoring/prometheus.yml @@ -0,0 +1,47 @@ +# Prometheus configuration for BUH Bot monitoring + +global: + scrape_interval: 15s + evaluation_interval: 15s + external_labels: + cluster: 'buh_bot_production' + environment: 'production' + +# Alerting configuration +alerting: + alertmanagers: + - static_configs: + - targets: [] + +# Scrape configurations +scrape_configs: + # Prometheus self-monitoring + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:9090'] + + # Node Exporter (host metrics) + - job_name: 'node_exporter' + static_configs: + - targets: ['node_exporter:9100'] + labels: + instance: 'host' + + # cAdvisor (container metrics) + - job_name: 'cadvisor' + static_configs: + - targets: ['cadvisor:8080'] + labels: + instance: 'containers' + + # Docker daemon metrics (если включено) + # - job_name: 'docker' + # static_configs: + # - targets: ['host.docker.internal:9323'] + + # BUH Bot metrics (если бот экспортирует метрики) + # - job_name: 'buh_bot' + # static_configs: + # - targets: ['buh_bot:8000'] + # labels: + # service: 'telegram_bot' diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..9fb3673 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,87 @@ +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Логирование + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + # Производительность + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + client_max_body_size 20M; + + # Gzip сжатие + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types text/plain text/css text/xml text/javascript + application/json application/javascript application/xml+rss; + + # SSL параметры + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # Rate limiting + limit_req_zone $binary_remote_addr zone=bot_limit:10m rate=10r/s; + limit_conn_zone $binary_remote_addr zone=conn_limit:10m; + + # Healthcheck endpoint + server { + listen 80; + server_name _; + + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + + location /metrics { + access_log off; + return 200 "nginx_up 1\n"; + add_header Content-Type text/plain; + } + } + + # Webhook endpoint (если используется) + # server { + # listen 443 ssl http2; + # server_name your-domain.com; + # + # ssl_certificate /etc/nginx/ssl/fullchain.pem; + # ssl_certificate_key /etc/nginx/ssl/privkey.pem; + # + # location /webhook { + # limit_req zone=bot_limit burst=20 nodelay; + # limit_conn conn_limit 10; + # + # proxy_pass http://buh_bot:8443; + # proxy_set_header Host $host; + # proxy_set_header X-Real-IP $remote_addr; + # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # proxy_set_header X-Forwarded-Proto $scheme; + # } + # } +}