Docker для локальной веб-разработки - заключение
Всем привет! Эта статья заканчивает серию переводов замечательных статей об использовании Docker для локальной веб-разработки.
В этой серии⚓︎
- Введение: почему это должно вас волновать?
- Часть 1: базовый стек LEMP
- Часть 2: посадите свои образы на диету
- Часть 3: трёхуровневая архитектура с фреймворками
- Часть 4: сглаживание ситуации с помощью Bash
- Часть 5: HTTPS для всего
- Часть 6: открываем локальный контейнер для доступа в Интернет
- Часть 7: использование многоэтапной сборки для внедрения воркера
- Часть 8: запланированные задачи
- Заключение: куда идти дальше ⬅️ вы здесь
Поздравляем!⚓︎
Если вы следили за этой серией с самого начала и дошли до этого момента, вы заслуживаете похлопывания по спине. Вы явно готовы потратить необходимое время и усилия, чтобы понять Docker, и вы должны гордиться — это не маленький подвиг!
Я надеюсь, что вы получили такое же удовольствие от изучения этих руководств, как и я от их написания, и что теперь вы ясно видите, как использовать Docker в своих интересах, и чувствуете себя комфортно при этом.
Тем не менее, вам может показаться, что некоторые камни остались нераскрытыми, поэтому я постараюсь перевернуть некоторые из них в этом заключении, так же, как я использовал введение, чтобы попытаться решить некоторые вопросы, которые могли возникнуть у вас перед тем, как вы решились на это.
А если этого недостаточно, комментарии всегда открыты!
«Вы сказали, что это не будет слишком медленно, но на самом деле это так»⚓︎
Если вы так считаете, то, скорее всего, вы используете Docker Desktop на macOS. И хотя я сам с удовольствием использую подобную систему, я понимаю, что производительность может показаться вам неоптимальной, особенно при выполнении сценариев (например, команд Composer).
Улучшения в этой области давно назрели, о чем свидетельствуют дискуссии, которые ведутся уже несколько лет, и пока на горизонте нет четкого решения. Вы можете экспериментировать с такими технологиями, как Mutagen или docker-sync, которые, кажется, дают некоторый результат, но лично я жду решения, которое бы легко интегрировалось с Docker Desktop без необходимости эзотерической настройки.
Ещё один популярный подход — смешивать сервисы Docker с собственными инструментами. Например, некоторые люди советуют использовать Laravel Valet на macOS для запуска PHP-приложения, а для всех остальных сервисов (таких как MySQL и Redis) использовать контейнеры Docker. Это философия таких проектов, как Takeout, например. Таким образом, вы получаете близкую к нативной производительность для приложений, для которых вы на самом деле пишете код, и при этом пользуетесь гибкостью Docker для всего остального.
Однако лично мне такой подход не по душе, поскольку он означает, что многое придется настраивать самому разработчику, в то время как я пытаюсь добиться уникальной, готовой к использованию среды разработки, которая подходит всем членам команды. Но если вы работаете как фрилансер или если ваша компания позволяет вам распоряжаться рабочей средой по своему усмотрению, это может быть хорошим решением.
Но опять же, как я повторял на протяжении всей этой серии, Docker — это всего лишь инструмент. Существует множество способов его использования — найдите тот, который подходит именно вам!
«Как мне это развернуть?»⚓︎
Хотя эта серия уроков посвящена созданию среды разработки, после того, как вы её создадите, один из следующих логичных вопросов — как вы развернете результат в среду постановки или продакшена. Я не буду подробно рассказывать об этом здесь, но могу дать вам несколько подсказок для начала.
Что на самом деле развёртывается⚓︎
Первое, о чем следует упомянуть, это то, что я никогда не развёртываю локальную установку как есть. Хотя некоторые облачные платформы поддерживают файлы docker-compose.yml из коробки, я обычно не использую их в контексте продакшена.
Обычно происходит так: образы фронтенда и бэкенда собираются и развёртываются отдельно через собственные конвейеры CI/CD, а соединения с любыми внешними сервисами, которые им нужны, настраиваются с помощью переменных окружения.
Например, в этой серии бэкенд приложения использует контейнер на основе официального образа MySQL для локального предоставления базы данных, детали подключения к которой задаются в файле .env бэкенда. На продакшене вместо этого может использоваться управляемая база данных, например, Amazon RDS, детали подключения которой будут вводиться в переменные окружения.
С точки зрения бэкенда, всё, что меняется от одного окружения к другому, — это значения параметров подключения; однако способ управления базой данных на самом деле совершенно другой.
Инфраструктура как сервис⚓︎
Ещё один момент, о котором следует упомянуть: платформы «инфраструктура как сервис» (IaaS) не всегда позволяют следовать лучшим практикам Docker, включая правило «один Docker-файл = один процесс».
Например, сервис App Service в Azure не позволяет легко управлять многоконтейнерными приложениями (в основном вам потребуется один сервис App Service на образ, что значительно увеличивает стоимость вашей инфраструктуры). Для экспериментальной среды мы не хотели платить за три разных экземпляра App Service, чтобы управлять Nginx, API и рабочим отдельно, поэтому мы объединили их в один образ, используя Supervisor для управления соответствующими процессами. Мы добились этого, просто добавив этап сборки production в Dockerfile API.
Конечно, вышеописанное не является проблемой, когда вы используете что-то вроде Kubernetes, но не всем командам это удобно.
Файлы приложения⚓︎
При развёртывании образа вашего приложения в среде постановки («staging») или в продакшене этот образ должен содержать копии файлов вашего приложения (включая его зависимости), поскольку монтирование локальной папки в такой среде неприменимо.
Копирование файлов в образ — это довольно простая инструкция:
Строка выше по сути означает «скопировать содержимое текущего каталога хоста (где находится Dockerfile) в рабочий каталог образа».
Небольшая оговорка заключается в том, что нам не нужны все файлы, которые будут скопированы — некоторые из них не являются необходимыми для продакшен-среды (например, README или даже сам Dockerfile), а то и вовсе опасны (например, файлы, связанные с Git). Как мы с этим справляемся?
Подобно файлам .gitignore в Git, в Docker есть файлы .dockerignore, которые позволяют вам указать, что исключить из контекста сборки при выполнении операций ADD или COPY. Я не буду вдаваться в подробности, но эта статья должна дать вам всю необходимую информацию.
Зависимости приложения⚓︎
Что касается зависимостей приложения, то, используя в качестве примера наше бэкенд-приложение, вы обычно добавляете в Dockerfile новый этап для установки пакетов Composer, файлы которого копируются на этап production, не сохраняя сам Composer (после установки зависимостей он больше не нужен вашей продакшен-среде).
Если назвать этот промежуточный этап build и предположить, что существует также этап base, содержащий только PHP-FPM и необходимые расширения PHP, то он будет выглядеть следующим образом:
FROM base as build
# Copy application files
COPY . .
# Install application dependencies
RUN composer install --no-scripts --no-autoloader --verbose --prefer-dist --no-progress --no-interaction --no-dev --no-suggest
FROM base as production
# Copy files from the build stage to the working directory
COPY --from=build .
Полученный образ вы можете поместить в реестр контейнеров (например, Docker Hub), который, в свою очередь, будет использован любой платформой IaaS, которую вы используете.
«Как насчет Kubernetes?»⚓︎
Kubernetes — это отдельная тема, но, как я уже упоминал во введении, он уже утвердился в качестве промышленного стандарта оркестровки контейнеров, что делает его всё более неизбежным при разговоре о Docker. Он поддерживается практически всеми основными поставщиками IaaS, что является хорошей защитой от привязки к поставщику и долгожданной консолидацией экосистемы Docker в целом.
Это заставило меня задуматься о локальной установке Kubernetes, которую можно было бы развернуть как есть в средах staging и production, или, по крайней мере, которая позволила бы мне использовать одну и ту же технологию оркестровки в разных средах. Я пока не придумал ничего конкретного, но мне были предложены такие инструменты, как Minikube, Skaffold или K3s, а некоторые инициативы, такие как Compose Specification, также, похоже, направлены на устранение этого пробела.
Потенциально с этим также связан Docker app — инструмент, реализующий стандарт Cloud Native Application Bundle (CNAB), направленный на упрощение комплектации, установки и управления контейнерными приложениями (с поддержкой Kubernetes). Я пока не совсем понимаю, что можно о нем сказать, но у меня есть ощущение, что это может стать чем-то интересным в ближайшем будущем. В их репозитории GitHub есть несколько примеров, если вы хотите взглянуть.
Пока не ясно, какой стандарт окажется на вершине (я бы ожидал некоторого сближения в какой-то момент), но снова похоже, что Docker Compose останется в центре всего этого, что я, безусловно, считаю хорошей вещью.
Всё дело в путешествии⚓︎
К этому моменту должно быть понятно, что Docker — это технология, к которой можно подойти с разных сторон, и, возможно, поэтому многим она кажется такой пугающей. Не знать, с чего начать, — лучший способ не начинать вообще, и моя цель здесь заключалась лишь в том, чтобы показать вам путь внутрь.
Хотя эта серия является отражением моих текущих знаний о Docker, мое собственное путешествие далеко не закончено. Мне ещё многое предстоит изучить, как я уже намекал, и я вполне допускаю, что в будущем способ использования Docker будет меняться.
Однако не позволяйте себе быть подавленным темпами развития Docker. Не торопитесь, и не забывайте регулярно отвлекаться от шума, чтобы применить на практике то, что вы уже знаете.
Нет необходимости постоянно следовать последним тенденциям — консолидируйте свои текущие знания и приобретайте новые инструменты только по мере необходимости. Как я уже говорил во введении, причина, по которой я в первую очередь обратил внимание на Docker, заключается в том, что я начал чувствовать себя не в своей тарелке из-за Homestead.
Особая благодарность⚓︎
Немного неловко добавлять этот раздел, как будто я только что закончил книгу, но именно так я чувствовал себя временами, когда писал эту серию. Прошло почти шесть месяцев с тех пор, как я начал работать над введением — на это ушло много моего свободного времени!
Но я не делал это полностью в одиночку — я хочу выразить благодарность и любовь моей девушке Анне, которая терпеливо просматривала каждую из этих объемных статей (включая эту), помогая мне звучать гораздо менее похоже на не носителя языка ❤️.
Этим постом я завершаю серию статей о Docker для веб-разработки, но я буду продолжать писать на эту тему и о веб-разработке в целом в будущем.
Оригинальная статья: Docker for local web development, conclusion: where to go from here (English)