Skip to content

Автоматического развертывание приложения (Backend + Frontend) в кластере Docker Swarm

License

Notifications You must be signed in to change notification settings

gdenis82/fastapi-docker-swarm

Repository files navigation

Инфраструктура FastAPI и Next.js в Docker Swarm (3 ноды)

FastAPI Next.js Docker Swarm PostgreSQL Redis Nginx Python Prometheus Grafana Traefik Portainer

Данный проект настроен для автоматического развертывания отказоустойчивого приложения (Backend + Frontend) в кластере Docker Swarm.

Структура проекта

  • infrastructure/: Скрипты для настройки и инициализации кластера (firewall, swarm init, registry, db).
  • deploy/: Конфигурационные файлы Docker Compose для разных уровней стека.
    • infrastructure.yml: База данных Postgres и Redis (размещаются на Manager ноде).
    • services.yml: Прикладные сервисы Backend и Frontend (Frontend на Manager, Backend на Worker нодах).
  • services/: Исходный код бэкенда (FastAPI) и фронтенда (Next.js).
  • update_services.py: Скрипт для сборки образов и обновления прикладных сервисов.

Автоматический деплой

1. Настройка конфигурации

Отредактируйте файл infrastructure/inventory.json, указав IP-адреса ваших нод, пользователей, пути к SSH-ключам и параметры БД.

2. Подготовка кластера и инфраструктуры

Запустите скрипт инициализации кластера:

python infrastructure/automate_deploy.py

Этот скрипт настроит ноды, объединит их в Swarm и развернет базу данных с Redis на менеджер-ноде.

3. Деплой приложений

Для сборки и запуска бэкенда и фронтенда используйте:

python update_services.py

Скрипт соберет Docker-образы локально, отправит их в реестр на менеджер-ноде, запустит их в кластере (Frontend на менеджере, Backend на воркерах) и автоматически применит миграции базы данных.

Применение миграций БД

Миграции запускаются автоматически в конце работы update_services.py. Скрипт находит один из запущенных контейнеров бэкенда и выполняет в нем команду alembic upgrade head.

Локальная разработка

Инструкции по локальному запуску всего стека (Backend, Frontend, DB, Redis) через Docker Compose или Makefile вынесены в отдельный файл: LOCAL_DEVELOPMENT.md

Особенности реализации

  • Разделение ролей: БД, Redis и Фронтенд работают на мастере (менеджере), Бэкенд распределяется по воркерам.
  • Сетевая изоляция: Все компоненты общаются внутри overlay-сети app_network.
  • Zero Downtime: Обновление сервисов происходит по стратегии start-first.

Важное примечание по Registry

Локальный Registry работает по протоколу HTTP (без SSL), поэтому Docker по умолчанию блокирует подключение к нему из соображений безопасности.

Вам НЕОБХОДИМО выполнить следующие действия:

  1. На вашей локальной машине (Windows/Mac/Linux):

    • Если вы используете Docker Desktop: зайдите в Settings -> Docker Engine.
    • Добавьте IP вашего менеджера в список insecure-registries:
      {
        "insecure-registries": ["85.198.86.165:5000"]
      }
    • Нажмите Apply & Restart.
    • Без этого шага команда docker push завершится ошибкой.
  2. На серверах (нодах):

    • Скрипт automate_deploy.py пытается настроить это автоматически в файле /etc/docker/daemon.json и перезапустить Docker.
    • Если деплой все равно не видит образы, проверьте содержимое файла на нодах вручную.

Особенности реализации пайплайна

Пайплайн автоматизации (automate_deploy.py) спроектирован с учетом требований безопасности и отказоустойчивости. Ниже приведен разбор ключевых решений:

1. Отказоустойчивый Docker Registry

  • Реализация: Реестр развернут как docker service create с ограничением на запуск только на менеджер-ноде.
  • Почему так: В отличие от обычного контейнера (docker run), Swarm-сервис автоматически перезапустится при сбое. Использование именованного тома registry_data гарантирует, что ваши образы не исчезнут при перезагрузке сервера.
  • Безопасность: Внедрена Basic Auth. Доступ к реестру (push/pull) возможен только по логину и паролю из inventory.json.

2. Безопасная работа с секретами

  • Реализация: Секреты создаются через stdin (стандартный ввод) SSH-сессии.
  • Почему так: Мы отказались от команды echo "pass" | docker secret create, так как она оставляет пароль в истории команд (.bash_history) и списке процессов (ps aux). Передача через stdin полностью исключает утечку секрета в логи системы.

3. Zero Downtime Deployment (ZDD)

  • Реализация: В docker-compose.yml установлены параметры update_config с order: start-first.
  • Почему так: Swarm сначала запускает новый контейнер и ждет, пока он пройдет проверку healthcheck. Только после того, как новая версия подтвердит свою работоспособность, старый контейнер будет остановлен. Это гарантирует отсутствие простоя при обновлении кода.

4. Уникальное тегирование образов

  • Реализация: Каждая сборка получает тег с временной меткой (например, :20240522_193005).
  • Почему так: Если использовать только тег :latest, Swarm может не заметить изменений в образе и не начать обновление. Уникальные теги гарантируют, что Swarm увидит новую версию и инициирует деплой.

5. Лимиты и резервирование ресурсов

  • Реализация: Для приложения жестко заданы limits (1GB RAM) и reservations (256MB RAM).
  • Почему так: Это защищает ноды от "прожорливых" процессов (Memory Leak). Лимиты не дают приложению уронить всю операционную систему, а резервирование гарантирует, что Swarm не попытается запустить контейнер там, где для него недостаточно ресурсов.

6. Изоляция и hardening Portainer

  • Реализация: Используется образ portainer-ce (вместо устаревшего portainer), внутренняя сеть agent_network с параметром internal: true, а также удален флаг --tlsskipverify.
  • Почему так: Версия Community Edition содержит патчи безопасности для уязвимостей 2023-2024 гг. Изоляция сети агентов и удаление флага небезопасной проверки TLS гарантируют, что к Docker API кластера сможет обращаться только сам Portainer, защищая трафик от прослушивания и вмешательства.

Доступ к сервисам и мониторинг

Адреса сервисов

После деплоя сервисы доступны по следующим адресам (при условии настройки DNS):

  • Frontend: https://tryout.site
  • Backend API: https://tryout.site/api
  • Documentation: https://tryout.site/api/docs
  • Grafana: https://grafana.tryout.site (порт 3000 закрыт для прямого доступа)
  • pgAdmin: https://pgadmin.tryout.site (порт 8080 закрыт для прямого доступа)
  • Portainer: https://portainer.tryout.site (порт 9000 закрыт для прямого доступа)

Настройка DNS

Для работы поддоменов необходимо добавить A-записи у вашего регистратора:

Поддомен Тип Значение (IP Менеджера)
@ (или основной) A 85.198.86.165
grafana A 85.198.86.165
pgadmin A 85.198.86.165
portainer A 85.198.86.165

SSL-сертификаты (Let's Encrypt) будут выпущены автоматически через Traefik при первом обращении к доменам.

Диагностика проблем

Если какой-то сервис (например, pgAdmin) не доступен:

  1. Проверьте статус сервисов:

    docker service ls

    Убедитесь, что количество реплик совпадает (например, 1/1).

  2. Просмотрите логи проблемного сервиса:

    # Для pgAdmin
    docker service logs fastapi_stack_pgadmin
    
    # Для Grafana
    docker service logs fastapi_stack_grafana
  3. Проверьте секреты:

    docker secret ls

Настройка источников данных в Grafana

При первом входе в Grafana (логин/пароль: admin/admin) необходимо подключить источники данных. Так как все сервисы находятся в одной Docker-сети app_network, используйте внутренние имена сервисов:

  1. Prometheus (Метрики):

    • URL: http://prometheus:9090
    • Access: Server (default)
  2. Loki (Логи):

    • URL: http://loki:3100

Данные для входа в pgAdmin

  • URL: https://pgadmin.tryout.site
  • Email: admin@admin.com (из inventory.json)
  • Пароль: admin_password_123 (из inventory.json)
  • Подключение к БД внутри pgAdmin:
    • Host: db
    • Port: 5432
    • Maintenance database: app_db
    • Username: postgres
    • Password: см. db_password в inventory.json

Очистка инфраструктуры

Для очистки всех нод от предыдущих деплоев, неиспользуемых контейнеров и образов используйте скрипт cleanup_nodes.py:

# Базовая очистка (удаление стеков, секретов, конфигов и сетей)
python infrastructure/cleanup_nodes.py

# Очистка с удалением всех данных (вольюмов)
python infrastructure/cleanup_nodes.py --volumes

# Полная очистка (удаление всего, включая выход из Docker Swarm и удаление образов)
python infrastructure/cleanup_nodes.py --full

Ручная настройка (для справки)

Особенности конфигурации

Zero Downtime Deployment

В docker-compose.yml настроены параметры для бесшовного обновления:

  • order: start-first: сначала запускается новый контейнер, затем останавливается старый.
  • healthcheck: Swarm ждет, пока приложение станет healthy перед тем, как переключить трафик и остановить старую версию.
  • parallelism: 1: обновление происходит по одной реплике за раз.

Мониторинг и логирование

В проекте настроен полноценный стек мониторинга:

  • Grafana (порт 3000): Визуализация метрик и логов.
  • Prometheus: Сбор метрик с сервисов и хостов.
  • Loki: Централизованный сбор логов.
  • Node-Exporter: Метрики операционной системы.
  • cAdvisor: Метрики контейнеров.
  • Portainer: Управление контейнерами (доступен по https://portainer.tryout.site).

Сканирование уязвимостей

При каждом деплое через update_services.py автоматически запускается сканирование образов с помощью Trivy.

  • Скрипт ищет уязвимости уровней HIGH и CRITICAL.
  • Если уязвимости найдены, скрипт запросит подтверждение перед продолжением деплоя.

Healthchecks

Все критические сервисы (DB, Redis, Backend, Frontend) снабжены проверками здоровья:

  • Swarm автоматически перезапускает зависшие контейнеры.
  • Обновление сервиса (Zero Downtime) не начнется, пока новый контейнер не станет healthy.

About

Автоматического развертывание приложения (Backend + Frontend) в кластере Docker Swarm

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors