Comments 45
Docker prodaction

По данному вопросу к сожалению я ничего сказать не могу

(орфография и пунктуация — авторская)
Весь смысл использовать докер — переносимость окружения. Если вы не знаете как это всё запустить на проде — ценность статьи стремится к нулю.
Я не просто так это пишу, это серьёзная проблема. Как выкатить это всё с дева на тест/прод, как дать понять программе что она теперь на проде (и не надо выводить отладочную информацию), как монтировать статику из php контейнера в apache/nginx контейнеры минуя хост (какой хост на проде-то?), как это всё масштабировать и т.д. и т.п.
Если мы не знаем как это всё будет запущено на проде — как тестировать? Как убедиться что на проде наш код не превратится в тыкву?
Контейнер должен быть один и тот же. Как вариант вашего предложения — запускать с нужными переменными. То есть на деве «ENV=DEV» на проде «ENV=PROD» и т.д.
Собирая разные контейнеры для Дев/Прод вы не сможете гарантировать, что в собранном через 5 минут Прод контейнере все установилось так же как и на Дев.
Пример: зависимости которые вытягиваются через npm(майтейнер что-то обновил/удалил/недоступен репозиторий). И вуаля — у вас не консистентный прод контейнер.
Перед продом контейнер всегда проходит полный QA цикл, если нет, то сочувствую.
Если npm стягивает не ту версию, на которой разрабатывался проект, то выкинуть на свалку этот менеджер пакетов.
у вас все прибито гвоздями и нет внешних зависимостей, либо есть но все со своих зеркал?
Несомненно, контейнер проходит все стадии QA. Но опять же, уберем npm — почему-то мне встречалось когда один и тот же пакет/билд фейлился каким-то образом при установке, чисто исходя из состояния звезд. rpm — может криво заехать из вашего нексуса и т.д.

Так и настраивая окружение для прода иначе, чем для дева вы рискуете, что оно будет работать иначе (это вообще ожидаемое поведение) или работать не будет вообще.

Статья не про Deploy используя Docker. Она больше о том, что попробовать разные языки/утилиты через контейнеры — очень просто.

Для прода нужно чтобы не было статических ссылок на другие контейнеры в конфиг файлах nginx.conf и т.д.


Значение хоста и порта в инструкциях типа SetHandler "proxy:fcgi://php:9000" должны приходить из ENV: SetHandler "${PHP_UPSTREAM}"


Конфиги и все файлы из src должны "запекаться" в image при помощи ADD/COPY инструкций Dockerfile.


Процесс надо разделить на 2 этапа. Сначала билдим все images, потом в docker-compose.yml ссылаемся на эти собранные image.


docker build -t my-php:dev-SNAPSHOT ./php
image: my-php:dev-SNAPSHOT

Программа должна работать без "volumes" в docker-compose (Их можно опционально добавлять при девепоменте, чтобы изменения в файлах хоста автоматически переносились в запущенный контейнер и не надо было билдить и запускать новый image каждый раз когда надо увидеть внесенные в код изменнения)


Далее надо использовать Rancher или Kubernetes чтобы это все дело оркестрировать на проде.

Программа должна работать без «volumes» в docker-compose (Их можно опционально добавлять при девепоменте, чтобы изменения в файлах хоста автоматически переносились в запущенный контейнер и не надо было билдить и запускать новый image каждый раз когда надо увидеть внесенные в код изменнения)

Но тогда получатся разные конфиги для prod и для dev, по моему это вообще не огонь, или альтернативного решения нет?

Конфиги и все файлы из src должны «запекаться» в image при помощи ADD/COPY инструкций Dockerfile.

А почему нельзя так оставить, обязательно в образ пихать?
По факту тоже самое получается, или в чем тонкость?
Docker отслеживает изменения docker-compose.yml или только изменения Dockerfile?
А почему нельзя так оставить, обязательно в образ пихать?

потому что намного удобнее дистрибьютить исходники вместе с инфраструктурой а не порознь.


По факту тоже самое получается, или в чем тонкость?

Ну вот когда доберетесь до продакшена и деплоев посерьезнее, тогда может быть разберетесь в тонкостях.


Docker отслеживает изменения docker-compose.yml или только изменения Dockerfile?

докер ничего не отслеживает. Если вы поменяли Dockerfile вы должны попросить его собрать новый образ. Если образ вдруг ничем не отличается (включая файлы которые вы копируете) он просто возьмет все слои из кэша.


Что до изменений в docker-compose — вы меняете не compose файлы а конфигурацию контейнера. Так что при запуске сервиса докер сравнит параметры контейнера и пересоздаст его если нужно (новый образ, другие параметры, новые переменные).

Но тогда получатся разные конфиги для prod и для dev, по моему это вообще не огонь, или альтернативного решения нет?


На проде вообще не будет docker-compose. Там будет окрестрация, так что конфиги все равно разные. Запекая файлы в образе мы гарантируем что все равно как этот контейнер запускается — он будет работать одинаково.

Фактически образ это исполняемый файл приложения. Исполняемый файл + переменные окружения = все что нужно для выполнения программы. Один из пунктов The Twelve-Factor App.

На проде вообще не будет docker-compose.

почему же? у меня вот есть (для проектов где не нужен кубернетис). docker-compose это тоже оркестрация, просто примитивная.


Ну а в остальном полностью согласен.

Это интересный план, но делать нужно всё с точностью наоборот :)
Для прода нужно чтобы не было статических ссылок на другие контейнеры в конфиг файлах nginx.conf и т.д.

Значение хоста и порта в инструкциях типа SetHandler «proxy:fcgi://php:9000» должны приходить из ENV: SetHandler "${PHP_UPSTREAM}"

В чём проблема с такими ссылками? И докер-композ и кубернетес спокойно работают с именами контейнеров. Запихивая их через ENV вы добавляете ещё одно место где может накосячить человек (человеческий фактор). Лишнее нарушение изоляции. В ENV вообще ничего ценного быть не должно.
Конфиги и все файлы из src должны «запекаться» в image при помощи ADD/COPY инструкций Dockerfile.

Конфиги как раз таки должы пробрасываться снаружи. Делается это для того чтобы эти конфиги не появились в ваших репозиториях (гит, докер). Для разного окружения — разные конфиги, потому засунуть их все в докерфайл — создать место с неопределённостью в работе (какой конфиг сейчас подгружен, какие значения?). Простой способ (не рекомендую) через ENV, чуть сложнее — через секреты. Можно записывать в райнтайм, опять же, зависит от того для кого.

Программа должна работать без «volumes» в docker-compose

Volumes могут быть не только для связи контейнер-дев машина, но и для связи контейнер-контейнер.

Далее надо использовать Rancher или Kubernetes чтобы это все дело оркестрировать на проде.

Насколько я понял — ранчер сейчас сам переходит на кубернетес, так что скоро это будет одно и тоже, просто у ранчера будет морда поудобней.
Простите, но Docker-compose никак не пакетный менеджер. Он служит для управления мульти-контейнерными приложениями.
«Локальный docker stack» как бы. Что бы поднять посмотреть, как примерно это чудо будет работать в кластерном режиме.
Ну как бы да, но это не то же самое, что управление кластером. Вот (не совсем в курсе как у кубернейтс) в режиме роя, докер имеет менеджер ноды, которые раздают таски шедулеру для изменения стейта роя. Вот это больше похоже на оркестрацию. Нежели compose, который скорее инструмент, что бы не не делать много «docker run ...» и «docker volume/network create ...» ручками.

Всё нет времени разобраться с кубернейтс. Скажите, как вам этот инструмент? Намного сложней сварма при реальной эксплуатации? Хочется простоты и полного понимания того, что происходит с кластером. Поэтому изначально был выбран сварм. Но вижу много хороших отзывов о кубернейтс и всё не могу для себя решить, стоит ли присмотреться.
Ну так кластеризация и оркестрация — не обязательно связанные понятия :)
Я, например, как раз таки не работал со свармом, так как когда искал систему для развёртывания натыкался на кучу негатива в сторону сварма, потому прошёл мимо, в сторону кубернетес.
Скажем так — для простых и средних приложений можно заюзать просто докер или докер композ, для чего-то серьёзного — кубернетес. Он большой, сложный, огромная куча функционала, но для мелких проектов это overkill.
Надо было наверно еще рассказать как из локальных сборок (используя docker-compose) потом всё перенести на прод, на swarm например. А еще лучше, как это сделать используя, например, Jenkins Blue Ocean (ибо тоже создан для облегчения понимания), как тестить сборки и получать вывод в дженкинсе же. Тогда наверно смысла было бы больше. Хотя, это наверно на книжку материала.
UFO landed and left these words here
А еще, сервисы должны быть готовы, что другие сервисы могут быть еще не готовы или внезапно упали в произвольном количестве. Об этом вроде Фаулер писал.
Чисто для ознакомления решил добавить на проект jenkins и sonarqube технологии, поднял проект на docker-compose добавил контейнеров для jenkins, sonarqube, database, API(backend-services), UI(контейнер NGINXа что б юзать как прокси, т. к. хотел оставить все на одном порте(повторяюсь делал для ознакомления и просто експерементировал(secure-low знаю))
Получилась интересная вещь:
project/standartUrl — редиректил на проект.
project/jenkinsUrl — на Jenkins.
project/sonarqube — на Sonarqube.
Потратил почти неделю на проблему: Nginx редиректил на проект и нормально его загружал, но при редиректе на SonarQube и Jenkins(далее tools) упрямо не хотел загружать css и js файлы. Перепробовал все (сначало проблема была в сабдомене для tools). Решив проблему
Решение
Казалось норм решение прокинуть в docker-compose volume с конфигурациями где указан sonar.web.context=/specifyUrl для Sonarqube
prefix=/specifyUrl для Jenkins
Но нет.
Пришлось перебилдить images тулзов с указанием вшупмнтх сетингов.

с сабдоменом, загрузка всеравно не происходила хотя сss&js стучались куда надо.
Озарило меня случайно
Озарение
В файле настройки Nginx приоритет чтения принадлежал регулярному выражению(потому грузились js css файлы только для проекта но не для тулзов)

Может кому поможет, или будет информативно)
Здравствуйте. Жаль, что у вас в статье все примеры docker-compose.yml картинками. я незрячий — их не вижу.
Хотел научиться работать с Docker, но не разобрался, как делать без особого труда виртуальные домены.
Для виртуальных доменов я юзаю https://github.com/jwilder/nginx-proxy
Он слушает 80 порт и посылает трафик в нужный контейнер. Как он узнает в какой контейнер слать? — для этого в контейнере прописываете параметр VIRTUAL_HOST=domainname.local
С ним очень удобно и просто управлять многодоменностью
Вот еще один мало обсуждаемый аспект (как мне показалось). Как же контейнерам подключать данные? Ведь информация же должна быть не убиваемой. Ну и вот одно из решений — подключение NFS в контейнеры. Этот вариант кажется хорош со всех сторон. Но вот какого-то простого how to нет. На docker-compose в основном примеры. А как же это сделать на docker swarm примеров мало. Может даже не так уж и мало, но авторы статей вываливают кучу опций монтирования, которые малопонятны для простых обывателей.

Тема интересная и новым людям моск иногда взрывает. Ибо репликаций одного контейнера может быть много, а может это и глобальный контейнер. И как это провернуть если система работает на 20 физических машинах например? В общем, неплохо было бы статью про то как сделать это сначала на compose, а потом безболезненно перенести на swarm.
Как же контейнерам подключать данные?

докер предоставляет вам абстракцию — волумы. Это что-то типа mount хостовой файловой системы. Причем как и в случае с mount, замаунтить можно хоть NFS хоть еще что.


Но вот какого-то простого how to нет.

  1. маунтить волумы через NFS не сказать что распространенная задача. Как правило все же данные либо хранятся в пределах хоста, либо напрямую контейнер к ним доступа не имеет (s3 какой). Ну и еще вариант с репликацией по сети (базы данных).


  2. для волумов существуют плагины, коих великое множество под самые разные файловые системы. В случае с NFS это к примеру вот такой вот плагин.

А как же это сделать на docker swarm примеров мало.

потому что все (ну как все, те кто хотят удобненько и быстро) используют кубернетис. Он это умеет.


Ибо репликаций одного контейнера может быть много

потому контейнеры по возможности должны быть stateless. Такие контейнеры по определению проще скейлить.

Технология, позволяющая легко (во всех смыслах) разворачивать необходимое рабочее окружение.

GIT для инфраструктуры — самое простое определение.


Пакетный менеджер (по аналогии с composer и npm, только у docker — контейнеры),

docker-compose, как предполагает его название (compose — композиция), это инструмент для оркестрацией контейнерами. Задача docker-compose удобно описывать сервисы (контейнера) и их конфигурацию а так же запускать это дело. За скачку образов отвечает сам докер.


Для начала определимся со структурой проектов:

судя по приведенному листенингу вы не определились.


Параметр build используется для того, чтобы заставить compose пересоздавать контейнеры.

типичная путаница в терминах, не "контейнеры" а "образы". Лучше бы потратили один-два абзаца что бы хотя бы самому для себя разобрать в чем разница.


Схематично это выглядит таким образом:

nginx отправляет запрос на php-fpm, а по вашей диаграмме они типа независимо обрабатывают запросы.


Как видите необязательно знать принцип работы docker, чтобы успешно с ним работать.

а потом толпы лемингов атакуют чаты с глупыми вопросами, которые устраняются вечером чтения документации/чтения статей.

Ну вот когда доберетесь до продакшена и деплоев посерьезнее, тогда может быть разберетесь в тонкостях.

Вам лень поделиться? Или вы не знаете?

судя по приведенному листенингу вы не определились.

Эээ и в чем же неопределенность? Для каждого образа есть своя директория в нужными параметрами, в каждом примере структура сохраняется.

типичная путаница в терминах, не «контейнеры» а «образы». Лучше бы потратили один-два абзаца что бы хотя бы самому для себя разобрать в чем разница.

Это не путаница, я не посчитал нужным вводить очередной термин, т.к. когда начинаешь читать про докер, на тебя сразу вываливается контейнеры, volume, образы, слои и др. Не вижу смысла забивать статью терминологией, если по контексту это не особо важно и критично.

Повторюсь, что статья в большей степени для начинающих, чтобы не особо вдаваясь в термины docker научиться с ним работать (с docker-compose). Чтобы узнать что такое докер в конце статьи ссылки приложены.

nginx отправляет запрос на php-fpm, а по вашей диаграмме они типа независимо обрабатывают запросы.

Это блок-схема, а не диаграмма активности или коммуникации.

а потом толпы лемингов атакуют чаты с глупыми вопросами, которые устраняются вечером чтения документации/чтения статей.

А следующий абзац лень прочитать? «Да, конечно, для тонкой настройки или сложных задач, необходимо уже углубляться в дебри docker, но в средне-статистическом случае — это не нужно.»
Вам лень поделиться? Или вы не знаете?

Лень если честно. В прочем делиться мне не жалко — https://github.com/fesor/project-skeleton.


Это не путаница

то есть вы сознательно вводите людей в заблуждение, ну ок.


Повторюсь, что статья в большей степени для начинающих

Начинающие должны сразу понять что такое образы, что такое слои и т.д. Лучше бы опустили в статье "как настроить apache" или php-fpm и указали бы ссылку на отдельную статью.


научиться с ним работать (с docker-compose)

но они же не научатся, в этом и проблема.


но в средне-статистическом случае — это не нужно

То что docker-compose не является менеджером пакетов знать нужно. То что есть образы и контейнеры из них разворачиваются знать нужно. То что можно зайти в контейнер, сделать commit и получить новый образ, знать нужно (что бы проще было объяснять как работает Dockerfile, как организовать деплоймент и т.д. и людям было бы проще когда они столкнутся с проблемами).

спасибо за ссылку на project-skeleton, а есть примеры скриптов/репозитория деплоя проекта?

Вот вам скрипт для деплоя проекта. Самый примитивный, без zero downtime и т.д. но так как даунтайм при деплое минимален меня такой вариант устраивает.


eval $(docker-machine env your-remote-host)
docker-compose pull
# скрипты которые необходимо запустить перед деплоем на новом образе
docker-compose run app bin/console doctrine:migrations:migrate -n
# подменяем контейнеры
docker-compose up -d

На проекта посерьезнее уже кубернетис за все отвечает, для которого масса готовых стратегий деплоя.

Чтобы в данной ситуации уничтожить контейнер, необходимо его остановить и удалить, но для начала, нужно узнать его ID:

Вместо этого можно использовать docker-compose stop для остановки всех контейнеров, либо docker-compose down для остановки и последующего удаления всех контейнеров.

Спасибо большое! Всё по делу. Почти заработало сразу!
Случилась правда у меня ошибка в контейнере апача
$ docker logs f7b8485a20b3
AH00534: httpd: Configuration error: No MPM loaded.

подключил модуль
LoadModule mpm_event_module modules/mod_mpm_event.so

заработал )
Еще, там где Dockerfile создаете
Для php мы добавили директиву build (подробнее), в которой указали директорию php, где хранится Dockerfile со следующим содержанием:
FROM php:7.2-apache


похоже всё же имели ввиду ввиду FROM php:7.2-fpm или я чего-то не понимаю?
у меня не заработал, к сожалению
httpd: Syntax error on line 66 of /usr/local/apache2/conf/httpd.conf: Cannot load /usr/lib/apache2/modules/mod_mpm_event.so into server: /usr/lib/apache2/modules/mod_mpm_event.so: cannot open shared object file: No such file or directory
хотя библиотека имеется:
docker exec -it app_php_1 ls /usr/lib/apache2/modules/mod_mpm_event.so
/usr/lib/apache2/modules/mod_mpm_event.so
А что apachectl -M отдает?

apachectl -M

Сейчас уже не помню, может быть его просто подрубить нужно, как сделал я:

LoadModule mpm_event_module modules/mod_mpm_event.so
я не могу стартовать контейнер:
AH00534: httpd: Configuration error: No MPM loaded.
чтобы это проверить
Тогда просто убедитесь, что в конфиге рядом с прочими LoadModule есть

LoadModule mpm_event_module modules/mod_mpm_event.so

И перезагрузите контейнер
его нет
#LoadModule mpm_event_module modules/mod_mpm_event.so
Если включаю:
docker logs php
httpd: Syntax error on line 66 of /usr/local/apache2/conf/httpd.conf: Cannot load modules/mod_mpm_event.so into server: /var/www/html/modules/mod_mpm_event.so: cannot open shared object file: No such file or directory
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6bcc8358705 httpd:2.4 «httpd-foreground» 31 seconds ago Restarting (1) 6 seconds ago php
d2defb0ed449 app_php «docker-php-entrypoi…» 31 seconds ago Up 26 seconds 80/tcp app_php_1
Почему-то он у вас его не там ищет. Долго разбираться. Может быть попробовать абсолютный путь прописать?

LoadModule mpm_event_module /usr/lib/apache2/modules/mod_mpm_event.so


Мне кажется у вас где-то есть расхождение с инструкцией. Попробуйте пройтись еще раз по статье и вашему проекту.
полностью прописать путь я пробовал. Тоже получил ошибку:
httpd: Syntax error on line 66 of /usr/local/apache2/conf/httpd.conf: Cannot load /usr/lib/apache2/modules/mod_mpm_event.so into server: /usr/lib/apache2/modules/mod_mpm_event.so: cannot open shared object file: No such file or directory
пробую все переделать с нуля…
Only those users with full accounts are able to leave comments. Log in, please.