1. Введение: Выполнение логики развертывания в фоновом режиме
Здравствуйте! В предыдущей части мы настроили среду промежуточного сервера и создали основную структуру вебхука FastAPI для проверки секрета при получении запросов от GitHub Webhook. В этом процессе мы предварительно включили код функций handle_deploy
и should_rebuild
в файл main.py
, что дало возможность заглянуть в основные идеи развертывания.
В этой четвертой части мы еще раз четко рассмотрим, как работает логика обработчика развертывания, которая была кратко обсуждена в третьей части, и сосредоточимся на том, как зарегистрировать этот вебхук FastAPI как службу Systemd, чтобы он автоматически запускался и работал стабильно даже после перезагрузки сервера. Теперь ваша система автоматического развертывания готова стать еще более надежной!
Тем, кто не видел предыдущие статьи, рекомендуется сначала ознакомиться с ними.
① Почему мы реализуем это самостоятельно?
② Общая архитектура и проектирование процесса
③ Настройка среды промежуточного сервера и основная настройка вебхука FastAPI
2. Взгляд на логику обработчика развертывания (handle_deploy
)
Функция handle_deploy
из файла main.py
, которую мы написали в третьей части, отвечает за выполнение реальной работы развертывания в фоновом режиме, когда поступает запрос от вебхука GitHub. Эта функция выполняет несколько ключевых задач.
Рекомендуется просмотреть пример кода третьей части вместе с приведенным ниже руководством.
2.1. Управление несколькими проектами и настройка переменных окружения
Чтобы управлять несколькими GitHub репозиториями (проектами) с одним вебхуком, необходимо указать, где находится каждый репозиторий на сервере. Функция handle_deploy
использует для этого словарь repo_paths
, и эти значения предназначены для считывания из переменных окружения сервера.
В примере кода появляется переменная окружения, такая как SAMPLE_PROJECT_1_PATH
. Вам нужно настроить актуальные пути для каждого проекта в файле .env
промежуточного сервера (этот файл должен находиться в той же директории, что и main.py
) или в файле службы systemd
следующим образом:
Фрагмент кода
# ~/projects/webhook_server/.env
# Секрет GitHub Webhook (настроенный в 3 части)
GITHUB_WEBHOOK_SECRET="your_github_webhook_secret_value"
# Актуальные пути к каждому проекту на сервере
SAMPLE_PROJECT_1_PATH="/var/www/my-project1"
SAMPLE_PROJECT_2_PATH="/home/user/another-project"
SAMPLE_PROJECT_3_PATH="/opt/third-project"
Функция handle_deploy
использует имя репозитория, полученное из полезной нагрузки вебхука, чтобы найти путь к проекту в словаре repo_paths
. Если сопоставленный путь не найден, остается предупреждение Unknown repository
и выполнение завершается.
Кроме того, в логике включено чтение дополнительных значений, таких как DEBUG
или COLOR
, из .env
файла каждого проекта (например, /var/www/my-project1/.env
), которые могут использоваться для выбора файла Docker Compose (docker-compose.dev.yml
или docker-compose.prod.yml
) и настройки имени Docker проекта. Это очень полезно для настройки процесса развертывания в соответствии с особенностями проекта.
2.2. Определение необходимости повторной сборки Docker образа (should_rebuild
)
Повторная сборка образа Docker каждый раз при развертывании занимает много времени и является неэффективной. Функция should_rebuild
использует команду diff
Git, чтобы обнаружить, изменились ли ключевые файлы, такие как Dockerfile
, requirements.txt
или .env
, которые влияют на сборку образа Docker.
Эта функция проверяет изменения с помощью команды git diff --name-only HEAD~1
и, если измененный список файлов включает заранее определенные trigger_files
(например, Dockerfile
, requirements.txt
, .env
, REBUILD_TRIGGER
и т. д.), возвращает True
, чтобы указать на необходимость повторной сборки образа.
В частности, файл REBUILD_TRIGGER
является полезным трюком, который принудительно вызывает повторную сборку, даже если файл пуст. Его можно вручную создать на сервере, когда требуется новая сборка порой по причинам, отличным от git pull
. Функция should_rebuild
автоматически удаляет этот файл, чтобы избежать ненужной повторной сборки при следующем развертывании.
2.3. Выполнение команд Git и Docker Compose
Функция handle_deploy
использует модуль subprocess
Python для выполнения команд git
и docker compose
на сервере.
-
subprocess.run(["git", "-C", repo_path, "pull"], check=True)
: Опцияcheck=True
вызываетsubprocess.CalledProcessError
, если возникает ошибка при выполнении команды Git, что позволяет вашей программе на Python зафиксировать это и соответствующим образом зарегистрировать ошибку. Опция-C
позволяет выполнить команду Git в указанной директории. -
subprocess.run(["docker", "compose", "-p", project_name, "-f", compose_file, "up", "-d", "--build"], check=True)
: В зависимости от результата функцииshould_rebuild
, команда будет выполнена сup -d
или с добавлением опции--build
для повторной сборки образа. Опция-p
указывает имя проекта Docker Compose, чтобы избежать конфликтов между несколькими проектами.
Эта логика позволяет эффективно обновлять услуги, получая последний код проекта с помощью одного запроса вебхука и повторно собирая образы только в случае необходимости.
3. Запуск вебхука FastAPI как службы Systemd
До сих пор мы вручную запускали сервер вебхука командой uvicorn main:app --reload
. Однако при перезагрузке сервера этот процесс исчезает, и служба останавливается даже при разрыве сеанса терминала. Чтобы избежать этого и добиться стабильной работы, необходимо зарегистрировать вебхук FastAPI как службу Systemd.
3.1. Почему нужно использовать Systemd?
-
Автозапуск: Сервис вебхука автоматически запускается при перезагрузке сервера.
-
Постоянное выполнение: Работает в фоновом режиме и не зависит от сеанса терминала.
-
Удобное управление: С помощью команды
systemctl
можно легко управлять запуском, остановкой, перезапуском, проверкой состояния и просмотром логов службы. -
Эффективное использование ресурсов: Как было описано во второй части, сам вебхук сервер является легким приложением на Python и запускается через Systemd, в то время как такие тяжелые инструменты, как Git или Docker, работают непосредственно с установленными на системе версиями, что помогает избежать ненужных настроек Docker в Docker и увеличения размера контейнеров.
3.2. Написание файла службы Systemd (*.service
)
Служба Systemd определяется с помощью файла .service
. Этот файл должен находиться в каталоге /etc/systemd/system/
. Мы создадим файл с именем github-webhook-deployer.service
. Я выбрал длинное название для простоты объяснения, но вы можете выбрать более короткое и понятное имя.
# Создание файла (требуется право sudo)
sudo nano /etc/systemd/system/github-webhook-deployer.service
Содержимое файла:
# /etc/systemd/system/github-webhook-deployer.service
[Unit]
Description=Служба развертывания GitHub Webhook
After=network.target # Этот сервис запускается после активации сети.
[Service]
User=your_username # Учетная запись пользователя, под которой выполняется этот сервис (например: ubuntu, your_user)
Group=your_username # Группа, под которой выполняется этот сервис (например: ubuntu, your_user)
WorkingDirectory=/home/your_username/projects/webhook_server # Директория с приложением FastAPI
# Настройка переменных окружения:
# 1. Поскольку приложение FastAPI загружает файл .env, переменные, используемые внутри приложения, такие как GITHUB_WEBHOOK_SECRET, не обязательно нужно загружать через EnvironmentFile. Но если вы хотите управлять всеми окружениями согласованно на уровне systemd, можете оставить путь EnvironmentFile.
# EnvironmentFile=/home/your_username/projects/webhook_server/.env
# 2. Чтобы вызвать системные команды git, docker, docker compose с помощью subprocess.run(), необходимо явно добавить путь, где находятся эти команды, в переменную окружения PATH.
# Примерный путь PATH включает обычные пути Linux и путь к bin Python виртуальной среды. Вам следует отредактировать 'your_username' и 'venv' в соответствии с тем, что соответствует вашей среде.
# Точный PATH можно проверить в файле .bashrc сервера или с помощью команды 'echo $PATH'.
Environment="PATH=/home/your_username/projects/webhook_server/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ExecStart=/home/your_username/projects/webhook_server/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000 # Путь к файлу uvicorn в виртуальной среде
Restart=always # Сервис всегда перезапускается после его завершения.
StandardOutput=journal # Стандартный вывод отправляется в журнал Systemd.
StandardError=journal # Стандартные ошибки отправляются в журнал Systemd.
[Install]
WantedBy=multi-user.target # Этот сервис запускается в многопользовательском режиме (обычное состояние запуска сервера).
Объяснение:
-
[Unit]
секция: Определяет общую информацию о сервисе (описание, зависимости).After=network.target
указывает на то, что этот сервис должен запускаться после того, как активируются сетевые службы. -
[Service]
секция: Определяет, как будет выполняться сервис.-
User
,Group
: Пользователь и группа, под которыми будет выполняться сервис. Обязательно должен быть установлен пользователь с правами Docker (например, пользователь, заданный командойsudo usermod -aG docker your_username
). -
WorkingDirectory
: Директория, в которой находится файлmain.py
приложения FastAPI. -
Environment="PATH=..."
: Этот аспект является ключевым. Когда вы вызываетеgit
,docker
,docker compose
и другие внешние команды черезsubprocess.run()
, переменная окруженияPATH
может отличаться от той, что установлена в.bashrc
и т.п. Поэтому необходимо явно указать путь, включая путь кuvicorn
в виртуальной среде (/home/your_username/projects/webhook_server/venv/bin
) и стандартные пути для исполняемых файлов в системе (/usr/local/bin
,/usr/bin
и т.д.). -
EnvironmentFile
(опционально): Приложение FastAPI загружает файл.env
с помощьюpython-dotenv
, так что переменные окружения, используемые внутри приложения (например,GITHUB_WEBHOOK_SECRET
,SAMPLE_PROJECT_N_PATH
и т.д.), не обязательно должны загружаться через эту настройку. Но если вы хотите, чтобыsystemd
явно загружал эти переменные перед запуском сервиса (для обеспечения согласованной среды для процессаExecStart
и его дочерних процессов), использованиеEnvironmentFile
может быть полезным. Вы можете комментировать или оставлять это в зависимости от предпочтения. -
ExecStart
: Реальная команда, запускающая сервис. Должен быть точно указан путь к исполняемому файлуuvicorn
в виртуальной среде. Опции--host 0.0.0.0 --port 8000
позволяют принимать запросы на 8000 порту с любых IP. -
Restart=always
: Если сервис по какой-либо причине завершится, Systemd автоматически попытается его перезапустить. -
StandardOutput=journal
,StandardError=journal
: Все выходные данные и ошибки сервиса отправляются в интегрированную систему логов Systemd —journalctl
.
-
-
[Install]
секция: Определяет, под управлением какого таргета сервис будет активирован.WantedBy=multi-user.target
означает, что сервис будет автоматически запущен при обычной многопользовательской загрузке сервера.
3.3. Регистрация и запуск службы Systemd
После создания файла службы вам нужно сообщить Systemd о нем и запустить службу.
# Уведомляем Systemd о новом файле службы.
sudo systemctl daemon-reload
# Настраиваем автоматический запуск службы при загрузке.
sudo systemctl enable github-webhook-deployer.service
# Запускаем службу.
sudo systemctl start github-webhook-deployer.service
# Проверяем состояние службы. Должно отображаться 'active (running)'.
sudo systemctl status github-webhook-deployer.service
Теперь ваш вебхук FastAPI будет автоматически запускаться даже после перезагрузки сервера и надежно ждать запросов вебхука в фоновом режиме.
4. Мониторинг и отладка вебхука FastAPI
Использование службы Systemd значительно упрощает проверку логов и диагностику проблем.
- Проверка состояния службы:
sudo systemctl status github-webhook-deployer.service
Эта команда показывает текущее состояние службы, последнее время выполнения и идентификатор процесса.
- Просмотр логов в реальном времени:
sudo journalctl -u github-webhook-deployer.service -f
Опция -u
указывает на логи определенной службы, а опция -f
позволяет постоянно выводить новые логи в реальном времени. Каждый раз, когда поступает запрос вебхука, сообщения журналов, установленные в main.py
, будут отображаться здесь.
Если служба не запускается или не работает должным образом, первым делом стоит проверить логи journalctl
на наличие сообщений об ошибках.
5. Заключение: Анонс следующей части
В этой четвертой части мы еще раз четко обсудили, как работает логика обработчика развертывания, которая была реализована в третьей части, и узнали о самом важном этапе — регистрации вебхука FastAPI как службы Systemd для надежного выполнения. Теперь ваш вебхук не будет беспокоиться даже после перезагрузки сервера.
В следующей пятой части мы завершим сборку системы, объединив последние кусочки пазла. Мы сосредоточимся на том, как настроить Nginx в качестве обратного прокси, безопасно выставить вебхук на внешний мир, внедрить HTTPS для повышения безопасности и, в конечном счете, протестировать фактическое автоматическое развертывание, связав вебхук с репозиторием GitHub. Ожидайте с нетерпением!
Комментариев нет.