deploy-production-readiness.md 5.4 KB

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

# Не хранить секреты в репозитории!
# Использовать:
# - Docker secrets (swarm mode)
# - HashiCorp Vault / AWS Secrets Manager / 1Password CLI
# - .env файл только на сервере (chmod 600), в .gitignore

2. Reverse Proxy (Nginx/Traefik/Caddy)

# 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 — автоматический HTTPS через Let's Encrypt
photoplaces.ru {
    reverse_proxy frontend:3000
}

api.photoplaces.ru {
    reverse_proxy backend:8080
}

3. Healthchecks для всех сервисов

# 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

# Добавить сервис бэкапа
  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. Логирование и мониторинг

# Добавить 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. Упрощённый деплой (одна команда)

# 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