Полный цикл в digital

Docker-compose

Docker-compose — это надстройка над докером, приложение написанное на Python, которое позволяет запускать множество контейнеров одновременно и маршрутизировать потоки данных между ними.

Для каждого проекта (кластера контейнеров) Docker создаёт свою сеть, где контейнеры могут обращаться друг к другу по именам, которые мы укажем в docker-compose.yml. Все настройки запуска кластера контейнеров находятся в этом же файле, который располагается в корневой директории проекта.

Преимущества Docker Compose

  1. Декларативный подход к созданию контейнеров
  2. Все необходимые контейнеры запускаются одной командой
  3. Автоматическое создание необходимых образов на основании Dockerfile каждого приложения
  4. Автоматическое создание изолированной сети для взаимодействия контейнеров
  5. Благодаря DNS возможно взаимодействие между контейнерами используя имена сервисов

Есть два подхода при работе с Docker, императивный и декларативный:

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

Синтаксис YAML-файлов

Строка

Строка — простая примитивная запись данных по типу ключ : значение. Строки можно записать двумя способами.

Однострочной записью:

string: This is a string.

Блочной записью:

---
string:
Это очень длинная строка,
которую сложно читать в однострочной записи,
так как она вылезает за пределы окна.
...

Блочная запись имеет три режима интерпретации:

  1. Стандартный (показан выше)
  2. С добавлением знака конца строки в завершении текста string: >
  3. с добавлением всех знаков конца строки при каждой новой строке string: I

Несколько строчных записей образуют словарь:

---
string_1: This is string 1.
string_2: This is string 2.
string_3: This is string 3.
...

Такая запись будет интерпретирована так:

{'string_1': 'This is a string 1.', 'string_2': 'This is a string 2.', 'string_3': 'This is a string 3.'}

Список

Список это набор разнородных данных. Списки могут быть трех видов:

  1. Простыми (одномерными)
  2. Вложенными (многомерными)
  3. Именованными

Пример простого, одномерного списка:

---
- element1
- element2
- element3
...

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

---
list:
- 2
- element2
- true
...

Вложенные именованные списки образуются добавлением двоеточия к нужному элементу, который станет названием вложенного списка, и добавлением отступов к другим элементам, которые станут элементами вложенного списка:

---
list_level_1:
- 2
- element2
- true
- list_level_2:
- element1
- element2
- element3
...

Образовать простой список с вложенными неименованными списками просто, достаточно указать дефис, сделать отступ и перечислить вложенные элемент:

---
-
- element_1
- element_2
- element_3
-
- element_1
- element_2
- element_3
...

Словарь

Словарь — это набор данных по типу ключ : значение. Словарь в YAML ничем не отличается от строк, то есть если мы сделаем такую запись:

---
author: Ivan Katkov
job: Tech Writer
skill: Normal
...

Мы получим словарь с 3 ключами, но если запись немного изменить на приведенную ниже, получится словарь с ключом author, в качестве значения будет другой словарь, содержащий: name, job, skill:

---
author:
name: Ivan Katkov
job: Tech Writer
skill: Normal
...

Мультивложенность элементов

Многоуровневая вложенность формируется отступами и спец. символами: двоеточием — знаком образования строки или ключа словаря и дефисов — символом образования списки или элемента списка.

Вложенные неименованные списки — дефис обозначает начало списка, а дефис с пробелом и название — является элементом списка:

-
  - Яблоки
  - Груша
  - Банан
-
  - Картофель
  - Редька
  - Капуста
-
  - Лук
  - Петрушка
  - Укроп

Вывод Python:

[['Яблоки', 'Груша', 'Банан'], ['Картофель', 'Редька', 'Капуста'], ['Лук', 'Петрушка', 'Укроп']]

Вложенные именованные списки образуются путём замены пустых дефисов, обозначающих список на именованную строку с двоеточием:

Фрукты:
  - Яблоки
  - Груша
  - Банан
Овощи:
  - Картофель
  - Редька
  - Капуста
Зелень:
  - Лук
  - Петрушка
  - Укроп

Вывод Python:

{'Фрукты': ['Яблоки', 'Груша', 'Банан'], 'Овощи': ['Картофель', 'Редька', 'Капуста'], 'Зелень': ['Лук', 'Петрушка', 'Укроп']}

Вложенные словари формируются с помощью именованных строк, двоеточий и отступов:

Фрукты:
 Яблоки:
  Красные:
   1кг.
  Зеленые:
   0,5кг.
 Груши:
  Гвидон:
   0,3кг.
  Велеса:
   0,1кг.

Вывод Python:

{'Фрукты': {'Яблоки': {'Красные': '1кг.', 'Зеленые': '0,5кг.'}, 'Груши': {'Гвидон': '0,3кг.', 'Велеса': '0,1кг.'}}}

Файл docker-compose.yml

  1. version обязательный тег, указывает на версию синтаксиса файла docker-compose.yml
  2. services обязательный тег, в него как бы заворачиваются наши два сервиса
  3. app название сервиса может быть произвольным, для каждого сервиса Docker создаст отдельный контейнер, в данном примере будет два контейнера, этот для приложения
  4. build: ./app инструкция build просит Docker создать кастомный образ на основании Dockerfile, ./app указывает местоположение Dockerfile для этого приложения. Когда вы введете команду docker-compose up -d которая начнет процесс создания контейнеров, сначала для сервиса app будет создан кастомный образ на основании Dockerfile который находится в папке ./app и только после этого из образа будет развернут контейнер для соответствующего сервиса
  5. mongo название сервиса может быть произвольным, для каждого сервиса Docker создаст отдельный контейнер, в данном примере будет два контейнера, этот для базы данных
  6. image: mongo инструкция image просит Docker скачать указанное название официального образа mongo которое будет найдено локально или на hub.docker.com и использовано для соответствующего контейнера mongo

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

Синтаксис файла docker-compose.yml

В docker-compose.yml очень важное значение имеют отступы, которые добавляются с помощью пробела, обычно один отступ равен двум пробелам. При этом, редактор кода Visual Studio Code позволяют нажимать Tab который автоматически конвертируется в пробелы, одно нажатие обычно равняется двум пробелам.

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

version: '2'
services:
    nginx:
      # используем последний стабильный образ nginx
        image: nginx:latest
        # маршрутизируем порты
        ports:
            - "8000:80"
        # монтируем директории, слева директории на основной машине, справа - куда они монтируются в контейнере
        volumes:
            - ./hosts:/etc/nginx/conf.d
            - ./www:/var/www
            - ./logs:/var/log/nginx
        # nginx должен общаться с php контейнером
        links:
            - php
    php:
        # у нас свой образ для PHP, указываем путь к нему и говорим что его надо собрать
        build: ./images/php
        # этот образ будет общаться с mysql
        links:
            - mysql
        # монтируем директорию с проектами
        volumes:
            - ./www:/var/www
    mysql:
        image: mariadb
        ports:
            - "3306:3306"
        volumes:
            - ./mysql:/var/lib/mysql
        # задаем пароль для root пользователя
        environment:
            MYSQL_ROOT_PASSWORD: secret
    pma:
      # используем последний стабильный образ phpmyadmin
        image: phpmyadmin/phpmyadmin
        restart: always
        links:
            - mysql:mysql
        ports:
            - 8183:80
        environment:
            # прописываем название нашего MySQL хоста
            PMA_HOST: mysql
            MYSQL_USERNAME: root
            MYSQL_ROOT_PASSWORD: secret

version

Файл docker-compose.yml должен начинаться с тега версии. Мы используем 2, это самая свежая версия на момент написания этого кода:

version: '2'

build

Указывает расположение файла Dockerfile, который будет использоваться для сборки этого контейнера:

build: ./images/php

command

Команда, которую нужно запустить после создания образа. Следующая команда означает запуск python ./server.py:

command: python ./server.py

client

Пользовательский интерфейс, или интерфейс командной строки, для взаимодействий с демоном Docker. Клиент Docker — это основной способ взаимодействия с Docker. Когда вы используете интерфейс командной строки (CLI) Docker, вы вводите в терминал команду, которая начинается сdocker. Затем клиент Docker использует API Docker для отправки команды демону Docker:

client:

command

Команда, которую нужно запустить после создания образа. Следующая команда означает запуск python ./client.py:

command: python ./client.py

network_mode

Ключевое слово network_mode используется для описания типа сети. Тут мы указываем, что контейнер может обращаться к localhost компьютера:

network_mode: host

image

Задает образ, который будет использоваться для сборки контейнера. Использование этой директивы предполагает, что указанный образ уже существует локально, либо в hub.docker.com. Используем последний стабильный образ nginx:

image: nginx:latest

restart

Сообщает контейнеру о перезапуске, если система перезагружается:

restart: always

volumes

Монтируем директории, слева директории на основной машине локально, справа куда они монтируются в контейнере:

volumes:
- ./hosts:/etc/nginx/conf.d
- ./www:/var/www
- ./logs:/var/log/nginx

environment

Определяет переменные среды, которые будут переданы в команду запуска Docker, например прописываем название нашего MySQL хоста, логин и пароль:

environment:
PMA_HOST: mysql
MYSQL_USERNAME: root
MYSQL_ROOT_PASSWORD: secret

port

Сопоставляет порт из контейнера с хостом следующим образом: порт компьютера:порт контейнера, приложение работает на 80-м порту, после перенаправления будет доступно на 8000-м порту:

ports: - "8000:80"

links

Связь контейнера с любыми другими контейнерами:

links: - php

working_dir

Задает рабочий каталог создаваемого контейнера:

working_dir: /var/www/html/

depends_on

Ключевое слово depends_on позволяет указывать, должен ли сервис в котором указан depends_on прежде чем запуститься, ждать когда будут готовы к работе другие сервисы. Например, чтобы сервис в котором указан depends_on дождался перед запуском готовности к работе сервиса под названием server, мы должны прописать:

depends_on: - server

networks

За сеть у нас отвечает ключ networks:

networks:
default:
driver: bridge
ipam:
config:
- subnet: 172.16.1.0/24
  1. default название нашей сети. Можете использовать любое название
  2. driver драйвер нашей сети
  3. ipam конфигурация сети, в данном случае мы указываем нашу локальную подсеть 172.16.1.0/24

Все контейнеры могут работать в одной сети которая устанавливается автоматически. Если прямой доступ по IP до контейнеров не нужен, значит в файле docker-compose.yml можно вообще убрать все упоминания о сетях.

Команды

В docker-compose.yml есть две пары команд для запуска и остановки приложения целиком:

  1. up запуск
  2. down остановка

В docker-compose.yml есть две пары команд для запуска и остановки отдельных приложений:

  1. start запуск
  2. stop остановка

Информация по командам:

docker compose --help

Запустить или вызвать все службы в файле docker-compose.yml:

docker-compose up

Пересобрать или вызвать все службы по новой в файле docker-compose.yml:

docker-compose up -d

Запустить только одну службу в файле docker-compose.yml:

docker-compose up название_службы

Просмотр запущенных контейнеров:

docker-compose ps

Откатить назад и удалить, всё что сделала команда up, останавливает и затем удаляет контейнеры и сети:

docker-compose down

Остановить запущеный контейнер не удаляя его:

docker-compose stop название_контейнера

Запустить остановленный контейнер:

docker-compose start название_контейнера

Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг