Docker-compose
- это средство, разработанное для помощи в определении запуска docker образов. Все что можно выполниять с помощью команды docker
(для запуска/остановки контейнера) можно упаковать в один файл и, с помощью 2-х команд, запускать и останавливать контейнеры.
Основным компонентом docker-compose является docker-compose.yaml
файл. В данном файле необходимо описать какие контейнеры нужно запустить, какие переменные в них необходимо передать, в какой сети будут запускаться контейнеры и тд.
Рассмотрим небольшой пример docker-compose.yaml
файла:
version : "3"
services:
mongo:
container_name: mongo
image: mongo:latest
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
MONGO_INITDB_DATABASE: test-db
ports:
- 27017:27017
volumes:
- ./mongodb-data/:/data/db
В данном примере описан простой docker-compose
файл (в формате yaml
) для запуска контейнера с базой данных mongodb. Создайте в пустой папке файл docker-compose.yaml
и скопируйте содержимое из примера в данный файл. Для использования файла для запуска контейнера введите команду в консоле:
cd /путь/до/файла/
docker-compose up -d
# если не получится, попробуйте использовать sudo:
# sudo docker-compose up -d
Проверку запуска можно выполнить с помощью команд:
docker ps
# если не получится, попробуйте использовать sudo:
# sudo docker ps
Остановим контейнер, для этого воспользуемся командой:
cd /путь/до/файла/
docker-compose down
# если не получится, попробуйте использовать sudo:
# sudo docker-compose down
С помощью docker run
можно выполнить все тоже самое. Команда для запуска будет выглядеть следующим образом (команда для примера, запускать ее не нужно!!!):
docker run -d \
--name mongo \
--restart always \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=root \
-e MONGO_INITDB_DATABASE=test-db \
-p 27017:27017\
-v ~/path/to/mongodb-data/:/data/db \
mongo:latest
Команда выглядит громоздкой. Запомнить ее очень сложно, а еще сложнее отследить через месяц после запуска контейнера, что и с какими параметрами было запущено. Поэтому голый docker run
почти никогда не используют. Вместо него используют "оболочки" работующие поверх, такие как docker-compose
.
Теперь, зная команды запуска и остановки контейнеров через
docker-compose
, вы можете самостоятельно проверить данный пример.
Рассмотрим каждую строчку docker-compose.yaml
файла в отдельности (для получения подробной информации, а также, для изучения дополнительных возможностей docker-compose
, советую обратиться к официальному мануалу).
version : "3"
- это версия самого приложения docker-compose
На текущий момент версия 3 является самой последней актуальной версией docker-compose
.
services:
- это заголовок, в котором указывается перечисление контейнеров для запуска. Например, имеется задача по установки 2-х баз данных mongo
, тогда docker-compose.yaml
файл может выглядеть следующим образом:
version : "3"
services:
mongo1:
image: mongo:latest
restart: always
mongo2:
image: mongo:latest
restart: always
Данный docker-compose.yaml
файл запустит 2 экземпляра базы mongo
. Ключи mongo1
и mongo2
- это названия сервисов (название может быть любым). Под каждым сервисом описываются настройки для запуска своего контейнера. Контейнеры могут быть любыми (не обязательно 2 экземпляра одного и того же приложения):
version : "3"
services:
mongo:
image: mongo:latest
restart: always
mysql:
image: mysql:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
В этом примере запускаются 2 контейнера с 2 разными БД (mongo
и mysql
).
Стоит также уточнить, что оба контейнера никак друг с другом не связаны. docker-compose
не связывает контейнеры, он служит только для запуска и их остановки.
image
- это название образа, который будет использоваться для запуска контейнера.
На прошлой лабораторной работе мы использовали Dockerfile
для создания образа. Для сборки образов использовали команду:
cd /путь/до/Dockerfile/
docker build -t <my_image_name> ./
<my_image_name>
- это название образа, который мы получили после его создания (название может быть любым). Данное название передается в image
в docker-compose.yaml
файле:
version : "3"
services:
mongo:
image: <my_image_name>
restart: always
container_name
- это параметр, который переопределяет название запущенного контейнера (это не название образа, это название контейнера, который будет запущен, значение можно задать любое). Данное название работает как некая ссылка на запущенный контейнер (на ровне с id
запущенного контейнера).
Данную ссылку используют во многих местах. Например, на прошлой лабораторной работе, для проверки логов запущенного контейнера приходилось использовать id
с помощью команды:
docker logs <container_id>
Теперь, при явном указании container_name
, обращаться к запущенному контейнеру можно через его имя:
docker logs mongo
Также, стоит отметить, что данное название должно быть индивидуальным для каждого запущенного контейнера.
Для проверки названия запущенного образа, необходимо выполнить команду:
docker ps
restart
- политика перезапуска контейнера. Она необходима для указания правила в случаях ошибки выполнения программы внутри контейнера. Например, если программа завершилась с ошибкой, при политике restart: always
контейнер перезапустится.
Существует 4 политики перезапуска, о данных политиках можно подробно почитать в официальной документации.
Рассмотрим пример (где запуск программы в docker
может завершиться с ошибкой):
version : "3"
services:
mysql:
container_name: mysql
image: mysql:latest
restart: always
Данное приложение запущено с политикой restart: always
и имеет ошибку. Проверим состояние контейнера:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
13a4c94d9f65 mysql:latest "docker-entrypoint.s…" 4 seconds ago Restarting (1) Less than a second ago mysql
В состоянии под колонкой STATUS
указано, что контейнер постоянно перезагружается.
Проверим логи приложения:
docker logs mysql
2021-10-02 13:21:42+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of the following:
- MYSQL_ROOT_PASSWORD
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
Приложение указывает на то, что не был передан пароль через переменные окружения. Остановим контейнер, и добавим переменную:
version : "3"
services:
mysql:
image: mysql:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
environment
указывает на переменные окружения, которые необходимо передать в контейнер, при его запуске. Например, можно передать переменную TZ
, или любую другую переменную, которая используется вашим приложением.
Например, при запуске контейнера с БД mongo
, можно передать логин/пароль пользователя и название БД:
version : "3"
services:
mongo:
container_name: mongo
image: mongo:latest
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
MONGO_INITDB_DATABASE: test-db
volumes
- указывает на массив монтированных директорий, файлов. Так как в примере запускается БД, необходимо сохранять данные во вне контейнера (ведь, если контейнер остановится, данные будут уничтожены вместе с ним):
version : "3"
services:
mongo:
container_name: mongo
image: mongo:latest
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
MONGO_INITDB_DATABASE: test-db
volumes:
- ./mongodb-data/:/data/db
./mongodb-data/:/data/db
указывает на то, что необходимо монтировать папку ./mongodb-data/
на лольной машине в папку /data/db
внутри контейнера. Таким образом можно передавать различные файлы внутрь программы (например, конфиги приложения), а также сохранять полученные файлы во время работы контейнера (данные БД).
ports
- указывает правила проброса портов изнутри контейнеера наружу.
В докере по-умолчанию имеется своя подсеть. При создании контейнера, каждому из них выдается свой адрес в этой подсети (взаимодействие идет через NAT). Контейнер может взаимодействовать с внешней сетью через общий шлюз докер подсети (например, скачивать внутрь себя приложения). Но из вне (за NAT-ом) мы не может взаимодействовать с внутренними приложениями контейнера (обращаться к приложению внутри докера по определенному порту). Для этого используется проброс портов через NAT, который указывается через переменную ports:
version : "3"
services:
mongo:
container_name: mongo
image: mongo:latest
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
MONGO_INITDB_DATABASE: test-db
ports:
- 9090:27017
Таким образом, проброс для порта 27017 выглядит так:
0.0.0.0:9090->(адрес выданный контейнеру из подсети docker):27017
Таким образом, обращаясь к адресу 0.0.0.0:9090
из локальной консоли вы будете обращаться к приложению, работающему по адресу 0.0.0.0:27017
внутри контейнера.
Для изучение сетей в docker будет выделено отдельное занятие.
-
Запустить программу написанную на прошлой лабораторной работе через
docker-compose
. Задание считается выполненным, если:- имеется
docker-compose.yaml
файл; - запуск и остановка контейнера осуществляются с помощью команд
docker-compose up -d
иdocker-compose down
; - С помощью команды
docker logs <id/name>
отображаются логи запущенного контейнера.
- имеется
-
Изучить приложения
prometheus
иgrafana
. Написатьdocker-compose.yaml
для их заупска. Задание считается выполненным, если:- имеется
docker-compoes.yaml
файл; - запуск и остановка контейнера осуществляются с помощью команд
docker-compose up -d
иdocker-compose down
; - Приложения открываются через Web UI (браузер).
- имеется