Как организовать грамотную доставку образа PHP приложения если необходим общий volume?
Всем привет! Заголовок вопроса не очень информативный, постараюсь объяснить:
Очень хотел бы с кем-нибудь обсудить один вопрос, чтобы прийти к бестпрактике.
Пытаюсь организовать грамотную доставку PHP приложения на прод с возможностью безшовных релизов (CD). Приложение состоит из трех контейнеров. Т.е. это классический PHP + APACHE + NGINX , при этом связка хорошо себя зарекомендовала и не хотелось бы отказываться и собирать всё в один image. Ранее доставлял код git-ом + рестартом контейнеров докер-композом. Теперь нужно чтобы доставлялись только образы.
Главная моя проблема на сегодня в том, что когда я делаю вольюм, условно voulume_public_folder который должен быть доступен всем контейнерам, то я лишаюсь возможности обновления кода при pull-е главного образа приложения (php в данном случае). Это происходит из-за того, что при первом контейнера (php) создается named volume, куда благодаря команде VOLUME в Dockerfile залетают файлы - круто. Но в следующий раз Docker уже не создает ничего и не обновляет соответственно (согласно документации).
Ответ: никак. Используйте volume если нужен некий storage. В противном случае организуйте контейнеры так, чтобы обновляемый в них код во время релизов был уже на этапе сборки образа.
В случае данного сабжа - если приложение не разделить на 3 сервиса, сервис будет один.
В итоге я убрал NGINX из связки и сделал образ из официального php-apache (а не php + apache)
Александр Карпов, так вы в вопросе спрашиваете про доставку кода. Код я бы вшивал в образ. Если речь о статике, то либо ее хранить в S3, либо пропихивать через volumes. Причем для всех контейнеров, кроме того, где php, для volumes статики надо указать :ro (readonly):
Дмитрий Свиридов, и как тогда обновлять статику? Вот допустим у вашего приложение сменились стили. В новой версии личного кабинета теперь другие css-ки. Как в таком случае вы бы обновили статику в volume или S3?
Александр Карпов, а, Вы про это) Я решил, что речь о всяких загруженных пользователями картинках и т.п. Js/css-файлы я бы вшивал в образ при сборке. Если у вас все в одном репозитории (php и фронтенд), то при сборке образов, которым требуется либо php, либо что-то из js/css, пропихивал бы туда все содержимое репозитория проекта (несмотря на то, что образу с Nginx php-скрипты не нужны). Но не через volumes докер-композа. То есть если у приложения сменились стили, то пересобираете образ, выставляете ему новый тег. Если нужно откатиться, то используете образ с предыдущим тегом.
Дмитрий Свиридов, верно же понимаю, что в таком случае делаем 2 образа PHP + APACHE и NGINX. При этом в обоих образах будут лежать сорцы. Т.е. чтобы привести версию приложения к какой-либо версии при этом рабочей, необходимо накатить два image соответствующей версии (т.к. теперь это будет крайне важно, чтобы не получить index.php v2 который ссылается на на index.css v1 )?
Я вот все эти сценарии уже проиграл и в голове и на схемах, и никак не могу понять, как выживают нормальные боевые проекты при таких сценариях. Неужели до таких костылей дело доходит.
Как по мне тогда уж лучше отказаться от связки либо всё в один образ затащить.
Александр Карпов, вообще есть правило, что один процесс на один контейнер, поэтому все в один образ тащить - плохая идея.
как выживают нормальные боевые проекты
В тех проектах, которые я видел, фронт и бэк разные репозитории имели, а код запихивался в образ при сборке. В образ, отнаследованный от Nginx, запихивался собранный вебпаком js, например (если собирается образ для фронтенда). Контейнеры управляются с помощью Nomad.
Всё, я, кажется, понимаю, в чем у вас проблема. Попробуйте так: если в Dockerfile вообще никакой код в образ не пихать в момент сборки образа, а указать нужные папки в volumes в docker-compose.yml для Nginx и Php контейнеров, то разве не пашет? Грубо говоря, так:
В секции, отвечающий за контейнер с Apache я не просто так не указал папку с кодом, а потому, что она ему не нужна. Если Вам не совсем понятно, как образ Apache увидит запущенный php, то в конце Dockerfile образа с php-fpm надо указать две команды:
EXPOSE 9000
CMD ["php-fpm"]
А в docker-compose для контейнера Apache надо указать, соответственно, links, и Apache настроить на TCP-сокет php-fpm контейнера с ним, указав порт 9000. Как-то так:
Дмитрий Свиридов, на самом деле апач примерно так и работает сейчас, просто я не использую флаг links, вроде как он устарел и без него работает.
А вот что касательно вольюмов, они ведь при условном docker pull не изменят ничего в папке на хосте?
Насколько я знаю, при таком вольюме в контейнере будет просто пустая /var/www в лучшем случае, потому что я не тащу код никак. Только image, только хардкор)
При этом если вольюм будет именованный то я смогу разок его накатить, при первом запуске контейнера.
Думаю, в том случае, который вы описали, где "форнт" и "бэк" это вообще разные проекты есть зерно здравого смысла. В моей ситуации там даже целый мешок зерна. Но я наверное не смогу отделить фронт от бэка сейчас.
они ведь при условном docker pull не изменят ничего в папке на хосте
docker pull просто затягивает свежий образ, если он есть. На содержимое папки, указанной в volumes это не влияет. Я имею в виду папку, которая "снаружи". Если вы что-то меняли внутри запущенного контейнера, то эти изменения потеряются при перезапуске.