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

И не заставляйте меня начинать, если вы разрабатываете с командой людей, и все вы подключены к одной и той же базе данных. Скажем так, это может стать рецептом для многих головных болей и часто встречающейся фразы «Кто-то снова уничтожил базу данных? ‹Вставить данные по вашему выбору›, с которыми я тестировал, больше нет! ». Это некрасиво и определенно неинтересно, когда данные не синхронизируются или полностью удаляются.

Решение? Контейнерные среды разработки

Сегодня я собираюсь радикально улучшить вашу разработку - по крайней мере, на местном уровне, а также, возможно, на более низких жизненных циклах и в производственной среде. Как? С помощью нашего надежного docker-compose.yml файла. Если вы не знакомы с Docker, я рекомендую вам ознакомиться с двумя моими предыдущими сообщениями в блоге, посвященными основам Docker и одной из самых полезных функций Docker, Docker Compose.

Если вы уже знакомы с Docker, продолжайте читать. Вы знаете Docker, знаете о его контейнерной природе и, возможно, даже использовали возможности контейнеров или целых контейнерных экосистем благодаря Docker Compose.

Но задумывались ли вы о том, как это может упростить разработку локализованных приложений? Подумайте об этом: использование docker-compose.yml для управления средой разработки решает проблемы, о которых я упоминал выше.

  • Все службы, перечисленные в docker-compose.yml, можно запустить вместе с помощью всего одной команды,
  • Нет шансов на конфликт портов (по крайней мере, во внутренней среде Docker), даже если приложения запускаются на одном и том же порте,
  • Каждая из служб знает о других службах и может без проблем подключаться к ним,
  • Вероятность синдрома «Это работает на моей машине» меньше, поскольку каждый контейнер использует один и тот же образ с одинаковыми зависимостями,
  • И, что лучше всего, каждая отдельная среда Docker может иметь свои собственные базы данных, к которым никто не может получить доступ (и впоследствии разрушить данные).

К тому же это очень просто сделать. Еще не заинтригованы?

Как Dockerize приложения

Я продемонстрирую простоту «докеризации» приложения с помощью полнофункционального JavaScript-приложения. Это приложение MERN, за исключением замены MongoDB базой данных MySQL.

Если вы хотите увидеть мое приложение полностью, код доступен здесь в Github.

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

Боковое примечание: если бы это были две (или более) отдельные службы, мне нужно было бы сохранить docker-compose.yml в обоих репозиториях, чтобы каждый мог быть развернут для локальной разработки. Разрабатываемая служба будет создавать новый образ каждый раз при вызове docker-compose up, и у нее будет доступ к необходимому образу Docker другой службы, хранящемуся в Docker Hub (или в другом месте, где вы решите хранить образы) с тегом версии, которую я хотел, в docker-compose.yml. Для производства также будет третий docker-compose-prod.yml, который будет использовать только проверенные и одобренные изображения. Но это выходит за рамки данной статьи.

Вернемся к файловой структуре проекта.

Структура файла приложения

root/
├── api/ 
├── client/ 
├── docker/ 
├── docker-compose.yml 
├── Dockerfile

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

Несмотря на то, что папки client и api содержатся в одном репо, я создал их с учетом микросервисов и модульности. Если одна часть становится узким местом и нуждается во втором экземпляре, или если приложение становится слишком большим и его необходимо разделить, это можно сделать без особого рефакторинга. Для достижения этой модульности и у моего API, и у клиентских приложений есть свои собственные package.json файлы с зависимостями, которые должны запускаться каждым приложением. Приятно то, что, поскольку в настоящее время это одно приложение, и оба приложения являются JavaScript, я могу иметь одно Dockerfile, которое будет работать для обоих.

Dockerfile

Вот как выглядит Dockerfile:

// download a base version of node from Docker Hub
FROM node:9
// create the working directory for the application called /app that will be the root
WORKDIR /app
// npm install the dependencies and run the start script from each package.json
CMD ls -ltr && npm install && npm start

Вот и все, что нужно для этого Dockerfile: только эти три команды. В docker-compose.yml есть кое-что еще, но за ним все еще легко следить, когда он сломан.

Docker-Compose.yml

На картинке выше вы можете увидеть две мои службы: api и client, а также базу данных (первое упоминание о ней до сих пор и одна из моих любимых вещей в Docker Compose).

Чтобы объяснить, что происходит, и клиент, и службы API используют один и тот же Dockerfile, который расположен в корне проекта (зарабатывая для них build: . путь сборки. Точно так же каждая папка монтируется внутри рабочего каталога, который мы указали в Dockerfile с volumes: ./<client or api directory>:/app. Я предоставил порт для каждой службы, чтобы упростить отладку отдельных служб, но было бы неплохо открыть порт для приложения только через пользовательский интерфейс. И, наконец, depends_on делает каждую часть приложения подождите, пока все детали не запустятся.

client зависит от api запуска ,api зависит от database запуска, и после того, как все учетные данные предоставлены в базу данных и образ извлечен из Docker Hub, он может запускаться. Я открыл порт в базе данных, чтобы я мог подключить Sequel Pro к своей базе данных и видеть объекты пользователей по мере их создания и обновления. Еще раз, это упрощает отладку по мере того, как я разрабатываю приложение.

Самая последняя строка базы данных о volumes - это особая строка, заслуживающая внимания. Таким образом сохраняются данные для приложения. Он сохраняется только локально на машине, на которой работает экосистема Docker, но обычно это все, что вам нужно для разработки. Таким образом, если вы используете Flyway, Liquibase или другой бегун SQL для создания таблиц и загрузки в них данных, а затем изменяете эти данные, чтобы протестировать функциональность приложения, изменения можно сохранить, чтобы, когда вы перезапустите приложение, данные будут такими, как вы их оставили. Это действительно здорово.

Итак, Dockerfile был рассмотрен, docker-compose.yml был объяснен, и был отмечен образ базы данных, извлеченный из Docker Hub. Мы готовы к работе.

Запустите приложение с одной строки

Пришло время запустить это приложение. Если вы разрабатываете это приложение локально впервые, введите docker-compose build в командной строке. Это создаст ваши два образа для клиентского приложения и приложения API - база данных MySQL поступает в виде образа прямо из Docker Hub, поэтому нет необходимости создавать этот образ локально. Вот что вы увидите в терминале.

Когда изображения будут построены, введите docker-compose up. Вы должны увидеть сообщение в терминале о запуске всех сервисов, а затем множество журналов кода, когда каждая часть запускается и подключается. И тебе должно быть хорошо. Вот и все. Готово и работает. Готово. Начать разработку.

Каждый раз, когда вы хотите остановить свое приложение, вы можете просто ввести docker-compose down в терминал, и службы будут корректно завершены. И данные будут храниться локально, поэтому, когда вы наберете docker-compose up, чтобы запустить резервное копирование приложений, ваши данные все еще будут там.

Заключение

Docker и Docker Compose могут значительно упростить вам веб-разработку. Вы можете создавать полностью функциональные изолированные среды разработки со своими собственными базами данных и данными с минимальными усилиями с вашей стороны, ускоряя время разработки и сокращая или избегая проблем, которые обычно возникают при настройке и создании проектов группами. Если вы еще не думали о «докеризации» процесса разработки, я настоятельно рекомендую изучить его.

Спасибо за чтение, надеюсь, это окажется полезным. Мы очень ценим аплодисменты и акции!

Если вам понравилось это читать, возможно, вам понравятся и другие мои блоги:

Ссылки и дополнительные ресурсы: