И еще один кусочек пазла:
Что мы уже имеем:
- Контейнер создан и работает на базе образа с symfony api
- Внутри работает runit, который перезапускает consumer сообщений (тут мы выиграли в скорости, потому что рестарт воркера теперь не приводит к полному пересозданию контейнеров)
Новые вводные: когда происходит релиз новой версии docker образа с приложением, надо мягко закончить активную задачу consumer'а и перезапустить контейнер на базе нового образа. Самым простым решением - переписать run скрипт следующим образом: #!/bin/sh exec 2>&1 cd /var/www/html
RELEASE_FILE="/var/www/shared/current_release"
#1. Запоминаем версию релиза ПЕРЕД запуском воркераSTART_RELEASE="unknown" if [ -f "$RELEASE_FILE" ]; then START_RELEASE=$(cat "$RELEASE_FILE") fi
echo "Starting Symfony consumer (Release: $START_RELEASE)..."
#2. Запускаем воркер. Он обработает 100 сообщений и завершитсяphp bin/console messenger:consume async --limit=100
#3. Читаем версию релиза ПОСЛЕ завершения воркераCURRENT_RELEASE="unknown" if [ -f "$RELEASE_FILE" ]; then CURRENT_RELEASE=$(cat "$RELEASE_FILE") fi
#4. Сверяем версииif [ "$START_RELEASE" != "$CURRENT_RELEASE" ]; then echo "Release changed from $START_RELEASE to $CURRENT_RELEASE. Killing container..."
#Завершаем PID 1, чтобы Docker пересоздал контейнерkill -TERM 1 exit 0 fi
echo "Release is the same. Runit will restart the worker inside this container."
#Небольшая пауза в 1 секунду перед выходом из скрипта (чтобы Runit не спамил #рестартами в случае моментального падения PHP, например, из-за ошибки в БД)sleep 1 Идея такая: вместе с образом на хост доставляется хэш последнего коммита, на базе которого построен образ. Этот хэш в виде файла смонтирован через -v внутрь каждого консьюмера. Однако, limit 100 заставит выполниться все оставшиеся задачи и только потом произойдет обновление. Так что воспользуемся встроенной механикой symfony messenger: https://symfony.com/doc/current/messenger.html#deploying-to-production А именно: bin/console messenger:stop-workers
Таким образом, имеем следующую последовательность:
- Сборка образа и доставка на прод меняет хэш коммита
- CI/CD скрипт выполняет bin/console messenger:stop-workers в каждом воркере
- Воркер заканчивает текущую задачу и выходит
- run скрипт обнаруживает изменение хэша коммита и выходит, из-за чего пересоздается контейнер уже на основе нового образа