Docker Compose – это инструмент, который был разработан, чтобы помочь определять многоконтейнерные приложения и совместно использовать их. С помощью Compose мы можем создать файл YAML для определения сервисов и с помощью одной команды развернуть все вверх или вниз.
Большое преимущество использования Compose заключается в том, что можно определить свой стек приложений в файле, сохранить его в корневом каталоге вашего проекта (теперь он контролируется версиями) и легко разрешить кому-либо другому вносить свой вклад в проект. Кому-то нужно будет только клонировать ваше репозиторий и запустить приложение compose. На самом деле, вы можете увидеть довольно много проектов на GitHub/GitLab, которые сейчас делают именно это.
Итак, с чего мы начнем?
Если вы установили Docker Desktop/Toolbox для Windows или Mac, у вас уже есть Docker Compose! В экземплярах Play-with-Docker также уже установлен Docker Compose. Если вы находитесь на компьютере с Linux, вам нужно будет установить Docker Compose.
После установки вы должны иметь возможность запустить следующее и просмотреть информацию о версии.
docker compose version
1. В корне проекта приложения создайте файл с именем docker-compose.yml.
2. В файле compose мы начнем с определения списка служб (или контейнеров), которые мы хотим запустить как часть нашего приложения.
services:
А теперь мы начнем переносить службу по очереди в файл compose.
Вспомним, что команда, которую мы использовали для определения нашего контейнера приложения, была такой.
docker run -dp 3000:3000 \
-w /app -v "$(pwd):/app" \
--network todo-app \
-e MYSQL_HOST=mysql \
-e MYSQL_USER=root \
-e MYSQL_PASSWORD=secret \
-e MYSQL_DB=todos \
node:18-alpine \
sh -c "yarn install && yarn run dev"
1. Во-первых, давайте определим службу и изображение для контейнера. Мы можем выбрать любое название для сервиса. Имя автоматически станет сетевым псевдонимом, который будет полезен при определении нашего сервиса MySQL.
services:
app:
image: node:18-alpine
2. Как правило, вы увидите command
рядом с определением image
, хотя никаких требований к порядку нет. Итак, давайте продолжим и перенесем это в наш файл.
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
3. Давайте перенесем часть команды -p 3000:3000
, определив порты для службы. Здесь мы будем использовать краткий синтаксис, но доступен и более подробный.
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
4. Далее мы перенесем как рабочий каталог (-w /app
), так и сопоставление томов (-v "$(pwd):/app"
), используя определения working_dir
и volumes
. Тома также имеют короткий и длинный синтаксис.
Одним из преимуществ определений томов Docker Compose является то, что мы можем использовать относительные пути из текущего каталога.
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
5. Наконец, нам нужно перенести определения переменных среды, используя ключ environment
.
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
Теперь пришло время определить службу MySQL. Команда, которую мы использовали для этого контейнера, была следующей:
docker run -d \
--network todo-app --network-alias mysql \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:8.0
1. Сначала мы определим новую службу и назовем ее mysql, чтобы она автоматически получала сетевой псевдоним. Мы пойдем дальше и также укажем изображение для использования.
services:
app:
# The app service definition
mysql:
image: mysql:8.0
2. Далее мы определим сопоставление томов. Когда мы запустили контейнер с помощью docker run
, именованный том был создан автоматически. Однако этого не происходит при запуске с помощью Compose. Нам нужно определить том в разделе тома верхнего уровня:, а затем указать точку монтирования в конфигурации службы. При простом указании только имени тома используются параметры по умолчанию. Однако есть еще много доступных вариантов.
services:
app:
# The app service definition
mysql:
image: mysql:8.0
volumes:
- todo-mysql-data:/var/lib/mysql
volumes:
todo-mysql-data:
3. Наконец, нам нужно только указать переменные среды
services:
app:
# The app service definition
mysql:
image: mysql:8.0
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
На этом этапе наш полный docker-compose.yml
должен выглядеть следующим образом:
services:
app:
image: node:18-alpine
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
mysql:
image: mysql:8.0
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
volumes:
todo-mysql-data:
Теперь, когда у нас есть наш файл docker-compose.yml
, можем его запустить!
1. Убедитесь, что никакие другие копии приложения / базы данных первоначально не запущены (docker ps
и docker rm -f <ids>
).
2. Запустите стек приложений с помощью команды docker compose up
. Мы добавим флаг -d
, чтобы запускать все в фоновом режиме.
docker compose up -d
Когда мы запустим это, мы должны увидеть вывод, наподобие этого:
Creating network "app_default" with the default driver
Creating volume "app_todo-mysql-data" with default driver
Creating app_app_1 ... done
Creating app_mysql_1 ... done
Вы заметите, что том был создан так же, как и сеть! По умолчанию Docker Compose автоматически создает сеть специально для стека приложений (именно поэтому мы не определили ее в файле compose).
3. Давайте посмотрим на журналы с помощью команды docker compose logs -f
. Вы увидите журналы из каждой службы, чередующиеся в один поток. Это невероятно полезно, когда вы хотите следить за проблемами, связанными со временем. Флаг -f
“следует” за журналом, поэтому выдаст вам вывод в реальном времени по мере его создания.
Если вы уже выполнили команду, вы увидите вывод, который выглядит следующим образом:
mysql_1 | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
mysql_1 | Version: '8.0.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
app_1 | Connected to mysql db at host mysql
app_1 | Listening on port 3000
Название службы отображается в начале строки (часто цветное), чтобы помочь различать сообщения. Если вы хотите просмотреть журналы для определенной службы, вы можете добавить название службы в конец команды logs (например, docker compose logs -f app
).
Совет: Ожидание базы данных перед запуском приложения
Когда приложение запускается, оно фактически сидит и ждет, пока MySQL будет запущен и готов, прежде чем пытаться подключиться к нему. Docker не имеет встроенной поддержки для ожидания полной загрузки, запуска и готовности другого контейнера перед запуском другого контейнера. Для проектов, основанных на Node.js, вы можете использовать зависимость wait-port. Аналогичные проекты существуют для других языков /фреймворков.
4. На этом этапе вы должны иметь возможность открыть свое приложение и увидеть, что оно запущено. И эй! Всё сводится к одной команде!
Если мы посмотрим на панель управления Docker, то увидим, что там есть группа с именем app
. Это “название проекта” из Docker Compose, которое используется для группировки контейнеров вместе. По умолчанию имя проекта – это просто имя каталога, в котором находился docker-compose.yml
.
Если вы прокрутите приложение вниз, вы увидите два контейнера, которые мы определили в файле compose. Имена также немного более описательны, поскольку они следуют шаблону <имя службы>-<номер реплики>
. Таким образом, очень легко быстро увидеть, какой контейнер является нашим приложением, а какой – базой данных mysql.
Когда вы будете готовы удалить все это, просто запустите docker compose down
или нажмите на корзину на панели инструментов Docker для всего приложения. Контейнеры остановятся, и сеть будет удалена.
Предупреждение
Удаление томов
По умолчанию именованные тома в вашем файле compose не удаляются при запускеdocker compose down
. Если вы хотите удалить тома, вам нужно будет добавить флаг--volumes
.
Панель управления Docker не удаляет тома при удалении стека приложений.
После завершения работы вы можете переключиться на другой проект, запустить docker compose up и быть готовым внести свой вклад в этот проект! На самом деле, немногое может быть проще этого!
В этом разделе вы узнали о Docker Compose и о том, как он помогает вам значительно упростить определение мультисервисных приложений и совместное использование ими. Вы создали файл Compose, переведя команды, которые вы использовали, в соответствующий формат compose.
На этом этапе начинается завершение учебного пособия. Тем не менее, есть несколько рекомендаций по созданию изображений, которые вы должны рассмотреть, поскольку существует большая проблема с файлом Dockerfile, который вы использовали.