Продвинутая работа с Docker — Docker-compose

Продвинутая работа с Docker — Docker-compose

KOD

Что такое Docker-compose?

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

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

Docker-compose.yml мало чем похож на знакомые нам уже docker-файлы. В отличие от них, docker-compose.yml записан не в декларативном ini-стиле как docker-файлы, а в древовидном YAML.

Создаем проект для запуска в Docker-compose

Наш проект состоит из двух связанных контейнеров: Nginx и php. Структура нашего проекта выглядит так:

  • www — каталог содержит index.html, index.php, подкаталог phpinfo. Эти файлы нужны для корректной работы Nginx и php-fpm. www также скопировано в каталоги nginx и php, из которых будут собираться контейнеры;
  • nginx — директория содержит конфигурационный файл nginx custom.conf, Dockerfile, по которому будет собираться nginx-контейнер и подкаталог www (копию корневого www), который будет скопирован в контейнер для проверки работоспособности и подменен в будущем;
  • php — директория содержит Dockerfile по которому будет собираться php-контейнер и аналогичный подкаталог www.

Такая структура проекта продиктована логикой сборки проекта. Сначала собираются образы Nginx и php из docker-файлов, расположенных в одноименных директориях, затем запускаются контейнеры в соответствии с инструкциями в Docker-compose.yml

Dockerfile Nginx

FROM nginx:mainline-alpine #Берем родительский образ Nginx

EXPOSE 80 # Открываем 80 порт

COPY custom.conf /etc/nginx/conf.d #Подменяем конфиг Nginx conf.d в контейнере на custom.conf

COPY ./www /var/www #Копируем содержимое www в /var/www

CMD ["nginx", "-g", "daemon off;"] #Запускаем Nginx как процесс.

Dockerfile php

FROM php:7.4-fpm #Берем родительский образ php:7.4-fpm

EXPOSE 9000 #Открываем 9000 порт

WORKDIR /var/www/ # Устанавливаем рабочим каталогом контейнера /var/www/

COPY ./www/ /var/www/ #Копируем содержимое хостового каталога www в директорию var/www/

CMD ["php-fpm"] #Выполняем команду php-fpm

В Docker-файле Nginx есть два ключевых момента для нашего проекта, которые нужно разобрать:

  • инструкция COPY custom.conf /etc/nginx/conf.d копирует custom.conf из локальной папки nginx и подменяет им conf.d в контейнере Nginx. Без него Nginx не отработает.
  • инструкция CMD с параметром ["nginx", "-g", "daemon off;"] запускает Nginx как процесс, а не как демон.

Теперь, чтобы были понятны наши следующие действия нужно обратиться к настройкам Nginx, тому самому конфигурационному файлу custom.conf, которым мы подменяли стандартный conf.d, находящийся в Nginx-контейнере.

 Внутри custom.conf выглядит так:

server {        listen 80;

        server_name 5.101.77.54;

        root /var/www;

        index index.html index.php;

        location ~ \.php$ {

                try_files $uri =404;

                fastcgi_split_path_info ^(.+\.php)(/.+)$;

                fastcgi_pass php:9000;

                fastcgi_index index.php;

                include fastcgi_params;

                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

                fastcgi_param PATH_INFO $fastcgi_path_info;

        }

Нас интересуют следующие параметры:

  • server_name — имя сервера, к которому мы обращаемся. В нашем случае, это IP-адрес нашей VPS.
  • root — корневая папка, в которой Nginx будет искать файлы для исполнения. Мы её будем подменять в дальнейшем через docker-compose.yml для визуализации процесса разработки.
  • fastcgi_pass php:9000 — проброс запроса на отдачу динамического контента в контейнер php на порт 9000.

Со структурой проекта, docker-файлами и настройками Nginx разобрались. Переходим к ключевому — разбираемся с docker-compose.yml.

docker-compose.yml — центр управления полётами

Docker-compose файл описывает процесс загрузки и настройки контейнеров. Разберём Docker-compose.yml, который мы подготовили для нашего проекта. Код нашего файла выглядит так:

version: "2.3" #Задаем версию docker-compose.yml

services: #Задаем контейнеры

  nginx: #Задаем название первого контейнера - nginx и настраиваем его

    build: ./nginx #Указываем откуда будет вестись сборка

    ports: # Указываем какие порты нужно пробросить наружу

      - "80:80"

    volumes: #Подключаем рабочий каталог с кодом проекта

      - ./www:/var/www

    depends_on: #Устанавливаем последовательность загрузки контейнеров

      php: # php-контейнер запуститься раньше Nginx

        condition: service_healthy #Устанавливаем условия при котором запуститься контейнер nginx

   php: #Задаем название первого контейнера - php и настраиваем его

    build: ./php #Указываем откуда будет вестись сборка

    volumes: #Подключаем тот же рабочий каталог с кодом проекта

      - ./www:/var/www

    healthcheck: #Проверка работы приложения внутри контейнера

      test: ["CMD","php-fpm","-t"] #Команда теста, которую мы хотим выполнить

      interval: 3s #Интервал попыток запуска теста

      timeout: 5s #Отложенность запуска команды

      retries: 5 #Количество повторений

      start_period: 1s #Через сколько стартовать тест после запуска контейнера 

Наш Docker-compose.yml невелик, однако он может быть огромным и иметь сложную структуру из разных типов организации данных: строк, списков, словарей. По началу даже в не очень сложном Docker-compose.yml можно наделать ошибок, которые на глаз не видны, поэтому перед запуском сборки проекта — проверьте код, каким-нибудь YAML-валидатором, например, yamllint.

В начале файла мы задали инструкцию version со значением 2.3 — это сделано специально, так как разные версии Docker-compose.yml содержат разный набор инструкций. Так в версии 3 нет инструкции healthcheck, а она критически важна для нас в этом проекте.

Инструкция healthcheck (блок php-контейнера) позволяет нам проверить работоспособность приложения в контейнере, указав с помощью другой инструкции test команду для тестирования. Смежные инструкции interval, timeout, retries, start_period устанавливают временные условия выполнения инструкции test.

Создайте VPS/VDS с виртуализацией Enterprise-уровня

Следующая логически связанная с healthcheck инструкция — depends_on (блок nginx-контейнера) — контроль порядка запуска. Логика работы depends_on такова: пока успешно не закончатся все действия указанные в блоке condition над контейнером заданным выше строчкой, контейнер, в котором расположена инструкция depends_on не запустится.

В нашем случае пока успешно не выполнится тест php-контейнера, Nginx-контейнер не запустится. Это сделано для правильной очередности загрузки инфраструктурных элементов нашего проекта.

depends_on: #Устанавливаем последовательность загрузки контейнеров

      php: # php-контейнер запуститься раньше Nginx

        condition: service_healthy #Устанавливаем условия при котором запуститься контейнер nginx 

Скажем еще несколько слов об инструкциях build и volumes:

  • build — указывает на директорию из которой будет собран контейнер, в ней должен быть dockerfile;
  • volumes — прокидывает локальную папку в контейнер. В нашем случае все изменения внесенные в файлы директории www будут автоматически доступны в контейнерах по пути /var/www.

Обратимся к логической блок-схеме для полного понимания процесса сборки и запуска нашего проекта, а потом перейдём непосредственно к сборке проекта.

 Схема взаимодействия структурных элементов проекта и их свойств

Теперь, когда мы понимаем внутренние взаимосвязи внутри проекта — настало время его собрать. Для запуска контейнеров через docker-compose используются следующие команды:

  • docker-compose build — собрать проект
  • docker-compose up -d — запустить проект
  • docker-compose down — остановить проект
  • docker-compose logs -f [service name] — посмотреть логи сервиса
  • docker-compose ps — вывести список контейнеров
  • docker-compose exec [service name] [command» — выполнить команду в контейнере
  • docker-compose images — список образов

Находясь в корневом каталоге проекта вызовем команду docker-compose up -d. Вот какие действия будут выполнены docker-compose: 1) Сборка образа php; 2) Сборка образа Nginx; 3) Запуск контейнера php; 4) Тест php; 5) Запуск контейнера Nginx. Проверим, запустились контейнеры командой docker ps. В ответ команда вернет сообщение следующего вида:

Если запустились не все контейнеры — введите docker ps -a и docker logs <название контейнера, который не запустился>. Вывод будет содержать коды и наименования ошибок. В нашем случае оба контейнера запустились и работают на нужных портах.

Проверим работу Nginx и php с помощью команды curl:

curl -I http://5.101.77.54/ 2>/dev/null | head -n 1 | cut -d$' ' -f2

curl -I http://5.101.77.54/phpinfo/ 2>/dev/null | head -n 1 | cut -d$' ' -f2 

В обоих случаях curl нам вернул код ответа 200. Это значит, что Nginx нашёл нужную страницу и отдал ее нам.

На этом сборка и тестирование проекта завершена, можно подводить итоги.

Что получается в итоге

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

Docker-compose.yml — конфигурационный файл в YAML-формате, описывающий логику запуска и взаимодействия контейнеров между собой и внешним миром. В сущности инструкции заложенные в docker-compose.yml по логике работы идентичны ключам команды docker run.

На первое место при работе с Docker-compose выходит структура проекта. Она должна следовать правилам работы Docker-контейнеров — в одном контейнере должен быть только один процесс. Хорошей практикой является составление процессной карты взаимодействия элементов вашего проекта между собой и её перенос на логику работы Docker-compose.


Report Page