Знакомство с docker-compose

Следующим шагом после установки Docker, я считаю, должно быть знакомство в docker-compose. Почему? Потому что, чаще всего, вы используете не один контейнер для задачи (проекта), а несколько. Да и сама идея микро-сервисов диктует именно такой подход. Например для сайта на WordPress, по хорошему, вам потребуется минимум три контейнера: контейнер с web сервером – например nginx, контейнер с WordPress и контейнер с базой данных. Можно конечно собрать собственный большой контейнер, на базе какого-нибудь nix дистрибутива, поставить в него и сервер и базу данных и WordPress запихнуть, но это будет монстр, который будет неудобно обслуживать, который будет занимать лишнее место и который будет в корне противоречить идее микро-сервисов. А поэтому – разделяй и властвуй.

Итак, возвращаясь к примеру в web-сервером, нужно три контейнера. Отлично. Есть вариант запускать их все вручную, используя команды типа

$ docker run --name some-wordpress -e WORDPRESS_DB_HOST=10.1.2.3:3306\
    -e WORDPRESS_DB_USER=... -e WORDPRESS_DB_PASSWORD=... -d wordpress

А еще не забывать про постоянное хранилище, для тех контейнеров, где нужно хранить данные между перезапусками

$ docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

Ну в общем не очень удобно, не очень наглядно, а самое главное – перенести это все на другой хост будет еще тем развлечением.

И в этом случае на помощь приходит docker-compose.

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

Ну и что бы не быть голословным: практический пример. Несколько упростим схему и предположим, что наш проект состоит всего из двух контейнеров: web-сервера и базы данных.

Для начала создадим новую директорию, назовём ее, например myProject. Название проекта docker-compose берет именно с названия директории, в которой расположен конфигурационный файл.

$ cd ~
$ mkdir myProject
$ cd myProject

Теперь нужно создать конфигурационный файл нашего проекта для docker-compose. Как ни странно, он называется docker-compose.yaml (можно использовать трехбуквенное расширение yml)

nano docker-compose.yaml

И вставляем в него такой код:

version: "3.7"

services:
  web-server:
    container_name: web-server
    image: nginx:stable-alpine
    restart: unless-stopped
    depends_on:
      - database
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./webserver:/var/www/html

  database:
    container_name: database
    image: istitch07/mariadb-alpine-rpi:latest
    restart: unless-stopped
    volumes:
      - ./database:/var/lib/mysql
    env_file: .env
    environment:
      - MYSQL_DATABASE=WebDB
    command: '--default-authentication-plugin=mysql_native_password'

Формат этого файла обычен для YAML разметки, для тех кто с ней не знаком – обращу внимание: все отступы делаются пробелами, использование табуляции не разрешается.

Да, важное: пример рассчитан на запуск на Raspberry Pi, то есть на процессоре с архитектурой arm/v7, если у вас другая архитектура процессора, вам потребуется использовать другой образ для базы данных.

Что в этом файле что: вначале идет описание версии файла конфигурации, в зависимости от версии может не быть доступны те или иные опции, чем больше версии, тем больше опций поддерживается, но следите за тем, что бы ваш docker-compose мог поддерживать эту версию. На данный момент самая актуальная версия: 3.8, поддерживается docker-compose начиная с версии 19.03.0.

Дальше идут описание сервисов, в нашем случае – контейнеров. Начинается с названия сервиса, например web-server:, а далее идет описание его конфигурации

ОпцияНазначение
container_name:Имя контейнера, может отличаться от имени сервиса
image:Какой образ использовать для контейнера. В случае отсутствия данного образа локально, будет произведена попытка скачать его с hub.docker.com (по умолчанию)
restart:Политика перезапуска контейнера после, например, перезагрузки. Допустимые значения:
"no" – не перезапускать;

always – перезапускать всегда;

on-failure – перезапускать только при возникновении ошибки в контейнере;

unless-stopped – перезапускать всегда, пока контейнер не будет остановлен вручную, например командой docker stop <имя контейнера>
ports:Какие порты следует пробросить в контейнер. Если для работы не требуется доступ к контейнеру извне докера – можно не пробрасывать, контейнеры внутри одного проекта и так могут обращаться к друг другу.
volumes:В случае если требуется хранить какие-либо данные между перезапусками контейнера, необходимо примапить хранилище с хостовой системы. Это может быть как внутреннее хранилище docker-а, так и конкретная папка на файловой системе, как в данном примере.
depends_on:Зависимости контейнера. В данном случае нам не имеет смысла поднимать веб сервер, пока не работает база данных, поэтому она указана в зависимостях этого контейнера.
env_file:Файл с переменными окружения. Для базы данных нужно задать пароли рута и пользователя базы, и имя этого пользователя. Это можно указать прямо в конфигурации, а можно вынести в отдельный файл. В данном случае я выношу это в файл .env
environment: Задать значение переменных окружения.
command:Перезапись команды по умолчанию. В моем примере мы передаем дополнительный аргумент –default-authentication-plugin=mysql_native_password

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

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

$ mkdir webserver database

Ну и осталось создать и наполнить файл .env

$ nano .env
MYSQL_ROOT_PASSWORD=RooTPassWord
MYSQL_USER=MySQLUser
MYSQL_PASSWORD=UserPassword

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

$ docker-compose pull

Эта команда говорит, что нам нужно скачать (или обновить уже имеющиеся) образы из репозитория. После того как образы скачены и установлены, можно из запускать:

$ docker-compose up -d

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

Проверить что все запустилось и работает можно как обычной командой докера $ docker ps так и командой $ docker-compose ps

(да, на моих скриншотах папка проекта называется tests, пусть это вас не смущает)

Останавлить или перезапустить один контейнер так же можно как командой $ docker stop/restart <container name> так и командой $ docker-compose stop/restart <container name>

А вот остановить все контейнеры входящие в один проект уже однозначно удобнее при помощи docker-compose: достаточно перейти в папку с его конфигурационным файлом и выполнить
$ docker-compose stop без параметров

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

На этом пока все, чуть позже напишу как запустить проект умного дома при помощи docker-compose на примере моего.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *