для чего нужен docker compose
Использование Docker Compose
Docker Compose — это средство, разработанное для помощи в определении и совместном использовании многоконтейнерных приложений. С помощью средства Compose можно создать файл YAML для определения служб и с помощью одной команды запускать и останавливать все, что нужно.
Большим преимуществом использования Compose является то, что можно определить стек приложения в файле, сохранить его в корне репозитория проекта (теперь поддерживается управление версиями) и легко предоставить другому пользователю возможность участвовать в проекте. Другому пользователю достаточно будет только клонировать репозиторий и начать создание приложения. Фактически в GitHub и GitLab можно увидеть достаточно много проектов, использующих эту возможность.
С чего же начать работу?
Установка Docker Compose
Если вы установили Docker Desktop для Windows или Mac, то у вас уже есть Docker Compose. В экземплярах «Play-with-Docker» уже установлен Docker Compose. Если вы используете компьютер Linux, необходимо установить Docker Compose с помощью приведенных здесь инструкций.
После установки вы сможете запустить следующую команду и просмотреть сведения о версии.
Создание файла Compose
Написание файла Compose начнем с определения версии схемы. В большинстве случаев лучше использовать последнюю поддерживаемую версию. Текущие версии схемы и матрицу совместимости см. в справочнике по файлу Compose.
Затем определим список служб (или контейнеров), которые требуется использовать как часть приложения.
Теперь приступим к переносу службы в файл Compose.
Определение службы приложений
Напомним, что эту команду вы использовали для определения контейнера приложения (замените в Windows PowerShell символы \ на символы ` ).
Сначала определите запись службы и образ для контейнера. Для службы можно выбрать любое имя. Имя будет автоматически преобразовано в сетевой псевдоним, что будет полезно при определении службы MySQL.
Одним из преимуществ определений томов Docker Compose является использование относительных путей из текущего каталога.
Определение службы MySQL
Теперь пора определить службу MySQL. Для этого контейнера использовалась следующая команда (замените в Windows PowerShell символы \ на символы ` ).
Наконец, осталось указать переменные среды.
На этом этапе полный файл docker-compose.yml должен выглядеть следующим образом.
Запуск стека приложений
После запуска должны отобразиться примерно следующие выходные данные.
Вы увидите, что том был создан, так же как и сеть. По умолчанию Docker Compose автоматически создает сеть специально для стека приложений (поэтому мы не определили его в файле Compose).
Если вы еще этого не сделали, вы увидите следующий результат.
Ожидание базы данных перед запуском приложения. При запуске приложения оно фактически ожидает, пока MySQL будет готов к работе, прежде чем попытаться подключиться к нему. В Docker отсутствует встроенная поддержка, позволяющая ожидать, пока другой контейнер будет полностью готов, запущен и подготовится к запуску другого контейнера. Для проектов на основе узлов можно использовать зависимость wait-port. Аналогичные проекты существуют для других языков и платформ.
На этом этапе вы сможете открыть приложение и увидеть, что оно запускается. И постойте! Вы сделали это с помощью одной команды!
Просмотр стека приложений в расширении Docker
Если взглянуть на расширение Docker, там можно изменить параметры группировки с помощью меню «шестеренки» и пункта «Group By» (группировать). В нашем случае необходимо просмотреть контейнеры, сгруппированные по имени проекта Compose.
Если развернуть сеть, вы увидите два контейнера, которые вы определили в файле Compose.
Завершение работы
Когда необходимо завершить работу, просто выполните команду docker-compose down или щелкните правой кнопкой мыши приложение в списке контейнеров в расширении Docker VS Code и выберите Compose Down (завершить Compose). Контейнеры будут остановлены, а сеть удалена.
После завершения работы можно переключиться на другой проект, запустить docker-compose up и подготовиться к работе с этим проектом. На самом деле нет ничего проще!
Резюме
В этом разделе вы узнали о средстве Docker Compose и о том, как оно помогает значительно упростить определение и совместное использование приложений с несколькими службами. Вы создали файл Compose, переведя команды в соответствующий формат.
Сейчас начинается завершающий этап обучения. Однако есть несколько рекомендаций по созданию образов, которые необходимо осветить, поскольку есть большая проблема с Dockerfile, который вы использовали. Так что давайте взглянем на это.
Docker и docker-compose для начинающих. Докеризуем интернет-магазин
Зачем мне понадобился докер? Ну не знал и не знал, сидел не умничал, сейчас-то что началось?
Разбираться с ним меня сподвигли вы, дорогие читатели. Да ладно? Серьезно. Четверть вопросов по интернет-магазину звучит примерно так: не работает, что делать? Почти всегда причина в том, что нужно настроить окружение. Поставить веб-сервер, завести php и mysql, развернуть базу и прочие рутинные штуки.
Вопрос разворачивания рабочего окружения для веб-проектов волновал меня давно.
Когда я начал заниматься первыми веб-проектами, то ухитрился поднять apache, php и mysql на windows 7. Было это лет 8 назад. История из серии «один раз получилось, но повторить не смогу». Это медаль, которую получаешь раз в жизни.
Вторая попытка осмыслить вопрос рабочего окружения случилась в 2015 году. Я тогда написал адовую статью, как развернуть окружение для веб-разработчика. Это было страшно, но я сам так работал. Схема предполагала винду как основную ОС, в винде ставилась виртуальная машина VirtualBox, в которой поднимался debian. В debian уже nginx, php, mysql и nodejs. Также ssh-сервер на виртуалке и ssh-клиент на винде. Все это волшебным образом соединялось вместе и реально работало! Я не жалею, что творил эту дичь, но вам не советую проделывать такой же путь. Просто не надо. Мир стал намного проще.
Но вопрос читателей меня не оставлял. Ведь все мы разные. Одни только начинают разбираться в веб-разработке. Другие работают на винде и им так удобнее. Третьи занимаются фронтендом и им вообще до фонаря эти php и базы данных. Они хотят потрогать javascript-код, а как его потрогаешь, если магазин просто не заводится?
Часто меня выручали системы вроде denwer и open server. Я сам ими не пользовался, но видел со стороны, как это работает, и поэтому советовал. В том же денвере apache, php и mysql поднимаются довольно просто, на мой взгляд. Судя по отзывам, некоторых читателей это выручало.
Но пора было делать следующий шаг.
Докер
Если приложение завернуто в докер, то оно запускается одной командой. По ходу статьи мы увидим, как это делается. Представьте, чтобы посмотреть, как работает авторизация или админка в интернет-магазине, вам нужно лишь скачать исходники и выполнить команду
Конечно, это все звучит здорово, но прежде чем так легко обращаться с докером, нужно разобраться как и что.
Основы докера
Разбираясь в теме, я прочитал десятка три статей по докеру. Но в голове все уложилось только когда я нашел вот эту
Рекомендую статью всем, кто хочет не просто скопипастить примеры из моей статьи, а понять, что такое докер, образы, контейнеры, как монтировать папки и файлы, как запускать команды и еще много полезных вещей. Статья большая, но написано по-человечески, простым языком, с примерами и аналогиями из жизни.
Докер на практике, docker-compose
Здесь случилось то же самое, что и с теорией по основам докера. Я перепробовал много разных вариантов, но то php не заводился, то mysql не подключался. Удалось все сделать только по примеру из этой статьи
Рекомендую читать всем, но особенно тем, кто уже разбирался с docker и docker-compose. Если вы знаете общие принципы или просто хотите завести свой проект, то лучше прочитать эту статью. Автор расписал коротко и по делу. Это не как у меня, статьи только с литром пива читать.
А еще мне понравилась структура проекта из поста. С разрешения автора в своей статье я использую его структуру и конфиги проекта практически без изменений, разве что слегка сократив.
docker и docker-compose. Аналогия для фронтендщиков
Процесс докеризации проекта напоминает мне сборку фронтенда.
В обоих случаях нам нужно решить набор задач. На фронте это собрать весь javascript в один файл и сжать его, препроцессить стили и тоже их сжать, оптимизировать картинки, запустить watcher. А с докером это поднять nginx, php, mysql и развернуть базу.
Для сборки фронта мы используем npm-пакеты, готовые библиотеки для сжатия и склеивания. В докере это готовые образы nginx, php, mysql.
Вот такая у меня аналогия. С общими делами разобрались, переходим к практике
Ставим docker и docker-compose
Докер отлично работает на линуксе и маке. Говорят, на 10-й винде тоже, но не пробовал. Я не знаю, какая у вас система, поэтому смотрите инструкции здесь.
После установки докера перезагрузитесь и проверьте, все ли в порядке
Если что-то не заработает, то наберите такие команды
Структура проекта
Тестовый проект default.test
Он будет очень простой. Закинем в папку www/default.test файлик index.php с содержимым
Вот и весь проект. На первом этапе мы всего лишь убедимся, что правильно настроили nginx и php. Давайте же посмотрим, как это сделать
Конфиг nginx
Это файл hosts/default.conf такого содержимого
Если вам приходилось настраивать nginx, то отличие найдете только одно. Раньше в локейшене \.php$ в fastcgi_pass вы писали что-то вроде
Такой конфиг более менее универсальный и подходит для локальной разработки несложных проектов. В статье мы рассмотрим 3 проекта и конфиги в них будут различаться только 4 строками.
Настраиваем php и Dockerfile для него
По идее можно не делать отдельный Dockerfile для php, а взять готовый образ. Именно так мы сделаем с nginx и mysql, когда будем настраивать docker-compose.yml. Но проблема в том, что nginx и mysql прекрасно работают из коробки, а с php немного иначе. Он тоже работает, но в официальный образ не включены никакие расширения, которые могут понадобиться при работе. Именно поэтому мы будем собирать php хитрее, через Dockerfile.
Давайте посмотрим на конфиг. Это файл images/php/Dockerfile
Напоминаю, что мы взяли конфиги из этой статьи. Я чуть сократил конфиг, поэтому читайте исходный, найдете там еще что-то интересное. Кратко что здесь происходит.
Да, Dockerfile для php посложнее, чем стандартный nginx-конфиг. nginx мы просто будем копипастить, меняя хост и пути. Здесь же, чтобы самому написать такой файл, нужно представлять, как работает php, где хранится php.ini, что такое рабочая директория и как ставить расширения. Но с другой стороны, базовые настройки меняться не будет, главное, разобраться со страшной портянкой в RUN.
А в докере нужно указать его в строке
Если честно, мне пока сложно понять, где и какие команды используются в тех или иных случаях. Поэтому не вижу других способов, чтобы для каждого конкретного случая копать документацию и гуглить. Но повторюсь, для наших проектов большего не понадобится. В Dockerfile мы больше заглядывать не будем.
Конфиг docker-compose.yml
Файл будет такого содержания
Разберем, что здесь написано.
Дальше раздел php. Здесь короче, потому что основное мы указали в Dockerfile
С конфигом docker-compose.yml пока все. Идем дальше
Правим файл hosts
Чтобы наш пробный сайт default.test заработал в браузере, нужно не забыть добавить его в файл hosts. Открываем /etc/hosts с sudo (на unix-системах) и добавляем в него
Точно так же, как и при работе с локальным веб-сервером. Сохраняем файл, закрываем
Запускаем проект
Наконец-то самое интересное, проверим, как все это работает. В консоли из корневой папки проекта запускаем команду
И ждем. Первый запуск будет проходить не быстро. В консоль будет сыпаться до фига всего разного, но можно будет разглядеть, как скачиваются образы ngnix и php, как выполняются команды RUN из php-шного Dockerfile, как запускаются контейнеры.
Если мы все сделали правильно, то увидим в консоли примерно такую картину
done напротив названий контейнеров говорит, что они успешно запущены. Идем в браузер, переходим на http://default.test:8000/ и видим полный расклад phpinfo. Работает!
Мы запустили наш первый проект, завернутый в докер. Не знаю, как вы, а я испытал какой-то священный трепет, когда все это завелось. С ума сойти, я могу просто взять этот проект, перетащить на другой компьютер и запустить его одной командой в консоли. Да, весь проект всего лишь выводит phpinfo, но эта простенькая штука станет базой для разворачивания более сложных проектов, связанных с базой данных да и вообще с чем угодно. Ниже мы научимся подключать в докере mysql и заведем интернет-магазин.
Но сначала немного отвлечемся и посмотрим, какие команды нам пригодятся при работе с docker-compose и вообще с проектами
Как работать с docker-compose
Первой командой, которую мы запустили, был docker-compose up. Команда анализирует конфиг docker-compose.yml, скачивает нужные образы, монтирует файлы и папки и запускает контейнеры. При этом процесс висит в консоли, а чтобы остановить его, нужно нажать ctrl+C, стандартно. А еще в консоли будут выводиться логи docker-compose.
При этом принудительно пересоберутся все образы. Это может быть полезно, когда мы что-то поменяли в конфигах и пока еще не понимаем, требует это пересборки или нет. Принудительный билд занимает больше времени, но я пока предпочитаю всегда его использовать. Все равно после самого первого сбора запуск проходит очень быстро, а потерпеть лишние 2 секунды не проблема.
Тогда докер запустит все контейнеры, но в фоне. Все будет работать точно так же, но чтобы остановить контейнеры, нужно будет запускать
А логи смотреть, запуская отдельно
Если мы разворачиваем приложение в продакшене, то конечно, запускать его стоит как фоновый процесс. Но в режиме разработки мне больше нравится держать консоль открытой и сразу смотреть логи. И не думать, нужна ли пересборка всех образов или нет. То есть запускать
Запускаем второй проект. Мое старое портфолио
Предлагаю немного передохнуть и закрепить информацию. Каким образом? Мы создадим второй проект. Он тоже php-ный, но чуть сложнее одного файла. Там уже подключаются шрифты, стили и javascript. Технически это не будет отличаться от первого default.test, но фишка в другом. Мы увидим, как просто нам теперь создавать новые проекты, а заодно и посмотрим на мое старое портфолио, которое я создал лет 6-7 назад. Это простой сайт на php, где рассказывается, какой я замечательный человек и разработчик.
Создаем новую папку www/w-portfolio.test. Кладем туда файлы проекта. Расписывать их нет смысла, все найдете в исходниках.
То есть мы скопировали конфиг из дефолтного default.conf и поменяли default на w-portfolio. Что может быть проще?
Осталось добавить в файл hosts строку
И перезапустить docker-compose
И открыть в браузере http://w-portfolio.test:8000
Итак, второй сайт разобрали, идем дальше.
Создаем проект интернет-магазина
Все то же самое, что и с проектом w-portfolio.test.
Создаем папку w-shop.test, копируем туда файлы магазина. Если вы читали статьи по магазину или админке, то в курсе, что это за магазин. Можете просто взять свои локальные файлы. А если нет, то взгляните, как этот самый магазин выглядит shop.webdevkin.ru и берите файлы из исходников
Дальше заводим nginx-конфиг w-shop.conf в папке hosts
И прописываем в /etc/hosts строку
Если вы прямо сейчас перезапустите docker-compose, то у вас откроется первая страница http://w-shop.test:8000/ и корзина http://w-shop.test:8000/cart.html. Будет работать даже добавление в корзину. А вот каталог с фильтрами, каталог с пагинацией и отправка заказов не заведутся, потому что там уже включается база. Давайте разбираться, как работать с mysql
Подключаем mysql
Добрались до самого интересного. Идем сразу в конфиг docker-compose.yml и добавим в services новый раздел mysql, вот так
А в раздел php добавим зависимость от нового контейнера
Разбираемся по порядку.
Все, база mysql у нас будет подниматься и будет работать. Но есть одно но. Как с ней работать руками? Чтобы прямо войти и посмотреть.
Конечно, можно подключаться к ней в консоли и фигачить create table и прочие хакерские заклинания, но хочется чего-то попроще. Люди давно изобрели PhpMyAdmin, который стоит на каждом хостинге и нам привычен. Давайте и его заведем в докер.
Устанавливаем PhpMyAdmin
В docker-compose.yml добавляем еще один контейнер
Готово, скоро будем пробовать. Но пока еще раз отвлечемся
Зависимости в docker-compose
Обратите внимание, как мы проставляли зависимости контейнеров друг от друга.
nginx зависит от php, то есть сначала стартует php, а потом nginx. php от mysql, phpmyadmin тоже от mysql и лишь mysql ни от кого не зависит. Она база, она сама по себе работает.
Когда мы запустим docker-compose снова, то увидим в консоли такую картину
Это как раз демонстрирует порядок запуска контейнеров. А останавливаются они в обратном порядке
Но это было отступление, погнали дальше, проверять mysql
Подключаемся к базе через PhpMyAdmin
Полез гуглить. Нашел, что в этом случае нужно из под рута выполнить такой запрос
Чтобы попасть в контейнер, нужно узнать его id. Набиваем docker ps и видим примерно такой список
После этого все заработало и PhpMyAdmin стал пускать без ограничений.
Создаем базу данных интернет-магазина
Docker-compose: идеальное рабочее окружение
Здрасте!
В последнее время все чаще задумываюсь об оптимальности рабочего процесса и хотелось бы поделиться своими изысканиями в данном вопросе.
В данном посте поговорим про docker-compose, который по моему мнению является панацеей в вопросе организации и оптимизации рабочего процесса разработчика.
Описывать все я буду почти на пальцах, поэтому если вы до этого ни разу не слышали про docker (что странно), ни разу с ним не работали и хотите в нем разобраться, то прошу под кат.
Предисловие
В статье я умышленно упрощаю некоторые моменты, не углубляюсь в детали и поверхностно касаюсь многих вопросов.
Делаю я это с полным понимаем своих действий, и считаю, что не нужно лазить под капот, если все работает.
Те, кто считают иначе — это ваше полное право, но только не нужно навязывать свою точку зрения.
Спасибо!
Docker
Технология, позволяющая легко (во всех смыслах) разворачивать необходимое рабочее окружение.
Подробнее можно узнать из ссылок в конце статьи, но лучше сейчас на это не переключаться, чтобы не забивать себе мозг.
Docker-compose
Пакетный менеджер (по аналогии с composer и npm, только у docker — контейнеры), позволяющий описывать необходимую структуру в одном файле (конфиге).
Подробнее также можно узнать из ссылок в конце статьи.
Docker-hub
Репозиторий контейнеров (по аналогии с packagist и npm).
Важное замечание: внимательно читайте описание к образу, 70-80% тупых вопросов там описано, не тратьте время на гугление.
Установка
Переписывать документацию docker я не стану, поэтому просто кину ссылки:
Установка обычного программного обеспечения (ПО), проблем возникнут не должно.
Если все же возникнут, то дальше можете не читать, вероятно вы случайно наткнулись на эту статью и разработку в целом.
Если вы устанавливали docker под Windows, то работать нужно через специальную консоль Docker Quickstart Terminal. После установки, на рабочем столе должен появиться соответствующий ярлык.
Структура проекта
Для начала определимся со структурой проектов:
CMD / Terminal
Для работы с docker и compose мы будем использовать всего несколько команд:
Описание прочих команд, можно найти на официальном сайте.
Перейдем непосредственно к делу.
apache
Начнем, пожалуй, с самого популярного сервера — Apache.
Создадим директорию проекта:
Конфиг будет выглядеть таким образом:
Что здесь происходит:
Создадим файл src/index.html в рабочей директории с содержимым:
Запускаем наш проект:
Переходим в браузер по адресу ПК и наблюдаем приветствие нашего сервера.
Чтобы уничтожить контейнеры нашего проекта, достаточно в консоле выполнить Ctrl+C.
Если докер работает через VirtualBox, то нужно заходить по IP виртуалки. При любом раскладе, если вы работаете через Docker Quickstart Terminal, то адрес выведется при запуске консоли.
Работа в фоновом режиме
Если вам необходимо запустить docker и далее работать в консоле, то можно запустить проект в фоном режиме:
После запуска, консоль будет доступна для работы.
Чтобы в данной ситуации уничтожить контейнер, необходимо его остановить и удалить, но для начала, нужно узнать его ID:
В моем случае получился такой вывод:
Теперь останавливаем и удаляем наш контейнер:
Либо можно поступить грубо и сразу удалить:
nginx
Конфиг nginx строиться по той же самой схеме, что и apache: образ, порты, рабочая директория. Выглядит файл таким образом:
Создаем файл src/index.html в рабочей директории с содержимым:
Заходим в браузер, и видим приветствие очередного сервера.
php + apache
Если говорить про связку PHP и Apache, то для нее уже есть готовый образ, поэтому про линковку контейнеров будем говорить далее. А сейчас просто конфиг:
Создаем файл src/index.php в рабочей директории с содержимым:
Проверяем его работу в браузере.
php + nginx
В данной связке php будет в формате fpm. Схематично это выглядит таким образом:
Соответственно нам нужно будет переписать конфиг сервера.
Для этого нужно будет слинковать помимо рабочей директории, еще и файл конфигурации сервера:
Если мы не укажем depends_on, то можем словить подобную ошибку:
Создаем файл /nginx/nginx.conf в директории нашего проекта. Сам конфиг выглядит таким образом:
После всех действий, директория нашего проекта выглядит таким образом:
Запускаем, проверяем, радуемся!
php + apache + nginx
Наверное, самая популярная связка для веб-проектов. Схематично это выглядит так:
Для того чтобы все настроить нам нужно будет также слинковать конфиг apache, и таким образом docker-compose будет выглядеть так:
Так как на просторах интернета я не нашел нормальный конфиг (оке, я просто не искал), а под рукой как раз docker, то решено было вытаскивать его из стандартного контейнера.
Уложилось все в 3 команды:
После выполнения данных команд, в текущей директории появится файл httpd.conf, который мы и будем использовать в качестве основы.
По сути, это простое копирование из запущенного контейнера.
Создаем файл /httpd/httpd.conf в рабочей директории, который после правок выглядит так:
Создаем файл /nginx/nginx.conf в рабочей директории со следующим содержимым:
В строке proxy_pass http://apache мы опять указываем не IP адрес, а название контейнера (вспоминаем про магию с hosts).
Для тестинга, нам нужно будет проверить, работает ли PHP и работает ли Apache.
Сформируем такую структуру проекта:
Содержимое .htaccess:
Содержимое index.php:
Содержимое index.html:
Если все настроено корректно, то картина должна быть следующей:
mariadb + phpmyadmin
Поговорим про базы данных.
Конфиг для подключения выглядит следующим образом:
Для mariadb и phpmyadmin мы указали директиву environment, которая содержит специфические для конкретного контейнера переменные (подробности можно посмотреть в репозиториях самих контейнеров).
В данном случае, это пароль для пользователя root.
Для phpmyadmin мы вручную указали директиву links:
Сделать это необходимо для того, чтобы phpmyadmin знал с какой базой соединятся.
Если бы контейнер mariadb назывался db, то указывать эту директорию было бы не нужно.
Для mariadb мы слинковали директорию с данными:
Сделано это для того, чтобы данные хранились в директории нашего проекта, а не внутри контейнера.
Если вы работаете не на linux машине, то у вас возникнут проблемы с размещением данных базы на локальной машине.
Эти непреодолимое обстоятельство, к сожалению, на данный момент не преодолено.
У кого есть решение просьба поделиться.
Однако по умолчанию (даже после уничтожения контейнера), данные базы сохраняются и вы можете пересоздавать контейнер сколько угодно раз — данные сохранятся в недрах локальной машины.
php + apache + nginx + mariadb + phpmyadmin
Ну, а теперь совмещаем наши конфиги, и получаем неплохое веб-окружение:
Для php мы добавили директиву build (подробнее), в которой указали директорию php, где хранится Dockerfile со следующим содержанием:
В данном файле мы обновляем репозитории и устанавливаем php модули (подробнее про docker-php-ext-install).
Также мы слинковали конфиг php, чтобы можно было его настроить нужным нам образом.
Содержимое php.ini можно взять, например, здесь.
Запускаем, проверяем, радуемся!
Если все сделано правильно, то index.php отработает без ошибок, а в директории project/mysql появятся служебные файлы базы.
Docker production
По данному вопросу к сожалению я ничего сказать не могу, зато может сказать официальная документация.
Если у вас есть опыт использования docker на боевых проектах, то просьба поделиться своим опытом в комментариях: стоит ли, какие трудности и подводные камни у вас возникли и др. полезную информацию для молодых и неопытных.
Заключение
Вот собственно и все, чем я хотел поделиться.
Как видите необязательно знать принцип работы docker, чтобы успешно с ним работать.
Да, конечно, для тонкой настройки или сложных задач, необходимо уже углубляться в дебри docker, но в средне-статистическом случае — это не нужно.
Если у вас есть что добавить, или вы заметили какой-то косяк, или вы с чем-то не согласны, то прошу в комментарии, обсудим 😉
Полезные ссылки (a.k.a список используемой литературы)
Если честно, я не понимаю откуда столько негатива.
Судя по комментариям, основные претензии к формулировкам и терминологии, и это с учетом того, что в предисловии я написал что умышленно упрощаю многие моменты.
Цель статьи — показать, как просто работать с docker-compose, как вместо того, чтобы разворачивать 100500 окружений и ПО для каждого своего проекта, можно использовать docker-compose и быть довольным.
Тут нет речи про prodUction (одного абзаца хватит), про deploy, про миграцию между dev и prod средой.
Нет, статья не об этом.
Большое спасибо krocos Caravus Vershnik Fesor за дельные комментарии.


