# Deploy: Production Readiness Checklist **Контекст**: В `deploy/` есть `docker-compose.prod.yml`, `deploy.sh`, `env.prod`. Локально — `docker-compose.yml` + `Makefile`. ## Суть **Проект разворачивается, но не production-ready** — есть риски безопасности, надежности и операционности. ## Критические проблемы (P0) | Проблема | Файл | Риск | |----------|------|------| | **Secrets в plain text** | `env.prod`, `docker-compose.yml` | Утечка БД, JWT, S3 при коммите / доступе к серверу | | **Нет healthcheck у backend/frontend в prod** | `docker-compose.prod.yml` | Контейнеры могут быть "up" но не готовы к трафику | | **Миграции не гарантированно накатываются** | `docker-compose.prod.yml:52` | `migrate/migrate` запускается как sidecar, нет retry логики | | **Нет reverse proxy (nginx/traefik)** | `docker-compose.prod.yml` | Прямой доступ к портам 8080/3000, нет SSL, нет rate limiting на входе | | **Single instance БД/Redis/MinIO** | `docker-compose.prod.yml` | SPOF, нет HA, нет бэкапов | | **Hardcoded IP в env.prod** | `env.prod:13,22,27` | Не переносимо, не работает за доменом | ## Рекомендуемые изменения ### 1. Secrets Management ```bash # Не хранить секреты в репозитории! # Использовать: # - Docker secrets (swarm mode) # - HashiCorp Vault / AWS Secrets Manager / 1Password CLI # - .env файл только на сервере (chmod 600), в .gitignore ``` ### 2. Reverse Proxy (Nginx/Traefik/Caddy) ```yaml # docker-compose.prod.yml — добавить сервис proxy: image: caddy:2-alpine ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data - caddy_config:/config depends_on: - backend - frontend ``` ```caddyfile # Caddyfile — автоматический HTTPS через Let's Encrypt photoplaces.ru { reverse_proxy frontend:3000 } api.photoplaces.ru { reverse_proxy backend:8080 } ``` ### 3. Healthchecks для всех сервисов ```yaml # backend healthcheck backend: healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 10s # frontend healthcheck frontend: healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 ``` ### 4. Database Backups ```yaml # Добавить сервис бэкапа postgres-backup: image: prodrigestivill/postgres-backup-local environment: POSTGRES_HOST: postgres POSTGRES_DB: photoplaces POSTGRES_USER: photoplaces POSTGRES_PASSWORD: ${DB_PASSWORD} SCHEDULE: "@daily" BACKUP_KEEP_DAYS: 30 volumes: - ./backups:/backups ``` ### 5. Логирование и мониторинг ```yaml # Добавить Loki + Promtail или ELK loki: image: grafana/loki:2.9 ports: ["3100:3100"] promtail: image: grafana/promtail:2.9 volumes: - /var/log:/var/log - ./promtail.yml:/etc/promtail.yml ``` ### 6. Упрощённый деплой (одна команда) ```bash # deploy/deploy.sh — улучшенная версия #!/usr/bin/env bash set -euo pipefail ENV_FILE="${1:-deploy/env.prod}" [ -f "$ENV_FILE" ] || { echo "Create $ENV_FILE from example"; exit 1; } # 1. Load secrets (support 1Password, Vault, etc.) source "$ENV_FILE" # 2. Build images with tags VERSION=$(git describe --tags --always --dirty) docker compose -f deploy/docker-compose.prod.yml build --build-arg VERSION="$VERSION" # 3. Run migrations (with retry) docker compose -f deploy/docker-compose.prod.yml run --rm migrations # 4. Deploy with zero-downtime (rolling update) docker compose -f deploy/docker-compose.prod.yml up -d --remove-orphans # 5. Health checks sleep 10 curl -sf http://localhost/health || { echo "Health check failed"; exit 1; } echo "✓ Deployed version $VERSION" ``` ## Чек-лист перед продакшеном - [ ] Все секреты вынесены из репозитория - [ ] Настроен HTTPS (Let's Encrypt / Caddy / Traefik) - [ ] Healthchecks на всех сервисах - [ ] Автоматические бэкапы БД (проверено restore) - [ ] Логи агрегируются (Loki/ELK) - [ ] Метрики собираются (Prometheus + Grafana) - [ ] Настроены алерты (down, high error rate, high latency) - [ ] Rate limiting на уровне прокси + приложение - [ ] CORS настроен только для продакшен доменов - [ ] Security headers (CSP, HSTS, X-Frame-Options) - [ ] Нагрузочное тестирование пройдено ## Связанные заметки - [[backend-rate-limiting]] — Rate limiter нужен Redis для прод - [[architecture-overview]] - [[decision-reverse-proxy]] ## Источник Задача: Code review PhotoPlaces — production readiness ## Теги #deploy #docker #production #security #monitoring #best-practice