Использование Docker для чайников

В одной из прошлых статей мы рассматривали как запустить контейнер Docker из образа. Основная идея Docker в том, что для каждого отдельного процесса должен быть создан отдельный контейнер Docker с окружением, нужным этому процессу. Но для сложных приложений здесь кроется проблема.

Например, для веб-приложения уже нужна база данных, веб-сервер, и возможно ещё интерпретатор PHP. Это уже три контейнера, настраивать и запускать их вручную не удобно, поэтому была придумана утилита docker-compose, которая позволяет управлять группами контейнеров, создавать их, настраивать, а также удалять одной командой. В этой статье мы разберемся как пользоваться docker для чайников. Подробно рассмотрим docker-compose, а также реальное применение утилиты.

Использование Docker для чайников

Поскольку эта инструкция про Docker для начинающих, я рекомендую сразу прочитать статью про запуск контейнера, вы поймете некоторые основы Docker, которые могут здесь вам пригодится. Там рассказано как всё делать вручную, а здесь мы уже поговорим как автоматизировать этот процесс.

1. Установка docker-compose

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

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

И дать ему права на выполнение:

sudo chmod +x /usr/local/bin/docker-compose

После этого вы сможете посмотреть её версию:

docker-compose --version

2. Создание проекта

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

version: 'версия'
networks:
  сети
volumes:
  хранилища
services:
  контейнеры

Версия указывает на версию синтаксиса файла, в разных версиях доступны разные ключевые слова, это сделано для обратной совместимости. Мы будем использовать версию 3.5. Далее нужно перечислить хранилища (volumes), сети (networks) и сами контейнеры.

Синтаксис YAML похож на JSON, здесь тоже есть пары ключ: значение, разделенные двоеточием, только тут значение может быть вообще нулевым, может содержать другие ключи, а также оно может быть массивом значений, тогда каждый элемент массива начинается с чёрточки "-". Но в отличие от JSON, здесь очень важны отступы, чтобы показать вложенность значений, поэтому не теряйте их.

Давайте создадим папку losst-docker и создадим в ней файл docker-compose.yaml:

mkdir losst-docker

vi losst-docker/docker-compose.yaml

version: '3.5'
services:

3. Добавление контейнеров

Рассмотрим содержимое самого простого пункта настройки контейнера:

имя_контейнера:
  image: образ:версия

Здесь нам обязательно надо указать имя будущего контейнера, а также образ, на основании которого он будет создан. Через двоеточие можно указывать версию контейнера. Версии можно посмотреть на Dockerhub они там отмечены как tags. Если версия не указана используется latest, последняя.

Например, добавим контейнер для веб-сервера Nginx:

docker-nginx:
  image: nginx

Уже имея эти данные в конфигурационном файле можно запускать контейнер.

4. Запуск контейнеров

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

cd losst-docker

docker-compose up

После этого контейнеры будут запущены, все их потоки вывода будут объединены в один и вам будет выводится информация в терминал. Чтобы остановить контейнеры достаточно нажать Ctrl+C. Если вы хотите запустить контейнеры в фоновом режиме используйте опцию -d:

docker-compose up -d

Остановить контейнеры, запущенные в фоновом режиме можно командой stop:

docker-compose stop

Команда down не просто останавливает все запущенные контейнеры, но и удаляет их:

docker-compose down

Остановите пока этот контейнер, мы продолжим его настройку.

5. Порты контейнера

Контейнер работает, но толку пока нам от него мало. С помощью docker мы можем пробросить порт 80 контейнера в основную операционную систему и получить к нему доступ. Для этого используйте директиву ports. Синтаксис такой:

ports:
- внешний_порт:внутренний порт

Например, пробросим порт 80 как 8094:

docker-nginx:
  image: nginx
  ports:
    - '8094:80'

Теперь вы можете перезапустить контейнеры и увидеть в браузере страницу, сообщающую о том, что Nginx работает по адресу http://localhost:8094:

Но это все ещё не интересно, потому что мы не можем размещать там свои файлы. Сейчас это исправим.

6. Монтирование папок

Для монтирования хранилищ или внешних папок хоста используется пункт volumes. Синтаксис очень похож на работу с портами:

volumes:
- /путь/к/внешней/папке:/путь/к/внутренней/папке

Например, давайте создадим в текущей папке проекта файл index.html и смонтируем эту папку вместо папки /usr/share/nginx/html/ контейнера:

vi index.html

<html>It's works!</html>

vi docker-compose.yaml

docker-nginx:
  image: nginx
  ports:
    - '8094:80'
  volumes:
    - ./:/usr/share/nginx/html/

После перезапуска контейнера вы увидите в браузере уже свою страницу. Это очень мощный инструмент, с помощью которого вы можете пробрасывать в контейнер всё, начиная от исходников и заканчивая конфигурационными файлами. Очень удобно.

7. Настройка хранилищ

Мы можем монтировать к контейнеру не только внешние папки, но и хранилища, создаваемые в docker. Для этого сначала надо добавить хранилище в главную секцию volumes. Например losst-vl:

volumes:
  losst-vl:

Большинству веб приложений необходима база данных, например, MySQL. Добавим ещё один контейнер для этой базы данных и добавим в него наше хранилище. Хранилище добавляется также, как и внешняя папка, только вместо папки указывается название хранилища:

docker-mysql:
  image: mysql
  volumes:
    - losst-vl:/var/lib/mysql
  environment:
    - MYSQL_ROOT_PASSWORD=password
    - MYSQL_DATABASE=database
    - MYSQL_USER=user
    - MYSQL_PASSWORD=password

 

Здесь мы ещё добавили пункт environment, в котором задали переменные окружения для контейнера. Они необходимы, для того, чтобы указать имя базы данных и пароль root, которые будут использоваться по умолчанию. Как видите, с переменными окружения нет ничего сложного.

8. Настройка сети

Контейнеры должны взаимодействовать между собой. У нас уже есть Nginx и MySQL, им пока не нужно обращаться друг к другу, но как только у нас появится контейнер для PhpMyAdmin, которому надо обращаться к MariaDB ситуация поменяется. Для взаимодействия между контейнерами используются виртуальные сети, они добавляются похожим образом на хранилища. Сначала добавьте сеть в глобальную секцию networks:

networks:
  losst-network:

Затем для каждого контейнера, которые будут иметь доступ к этой сети, надо добавить сеть в раздел networks.

Далее контейнеры будут доступны по сети по их имени. Например, добавим PhpMyAdmin и дадим ему доступ к базе данных:

docker-phpmyadmin:
  image: phpmyadmin/phpmyadmin:latest
  ports:
    - "8095:80"
  environment:
    - PMA_HOST=docker-mysql
  networks:
    - losst-network

 

 

Здесь в переменной PMA_HOST мы ссылаемся на хост docker-mariadb, который благодаря общей сети этих контейнеров доступен. Аналогично в контейнере docker-mariadb, наш контейнер с PhpMyAdmin доступен как docker-phpmyadmin. Вы можете открыть адрес http://localhost:8095 и авторизоваться чтобы проверить, что база данных работает:

9. Модификация контейнера

Это уже более сложные вещи, но зато вы разберетесь с Docker на практике. В большинстве случаев можно обойтись без модификации контейнера, иногда туда надо скопировать специфические конфигурационные файлы либо установить дополнительное программное обеспечение, для таких случаев docker-compose позволяет создавать свои контейнеры на основе уже существующих образов. Для этого надо создать файл Dockerfile на основе которого будет создаваться контейнер. Давайте добавим контейнер php-fpm и установим в него несколько расширений php с помощью Dockerfile.

Сначала создадим папку для файлов контейнера:

mkdir php-fpm

vi php-fpm/Dockerfile

FROM php:7.2.26-fpm-stretch
RUN docker-php-ext-install pdo pdo_mysql pcntl

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

  • FROM - образ, на основе которого будет создаваться наш образ;
  • RUN - выполнить команду в окружении образа;
  • COPY - скопировать файл в образ;
  • WORKDIR - задать рабочую папку для образа;
  • ENV - задать переменную окружения образа;
  • CMD - задать основной процесс образа;

Теперь надо добавить новую секцию в наш docker-compose.yaml. Здесь вместо image мы используем директиву build, которой надо передать путь к папке с конфигурацией образа:

docker-php-fpm:
  build: 
    context: ./php-fpm
  volumes:
    - ./:/var/www/
  networks:
    - losst-network

Дальше, раз мы уже добавили php-fpm надо примонтировать для Nginx верный конфиг, который будет поддерживать php-fpm. Создайте папку nginx и поместите в неё такой конфигурационный файл:

mkdir nginx

vi nginx/site.conf

server {
listen 80;
server_name _ !default;
root /var/www/;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass docker-php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}

Осталось немного поправить конфигурацию nginx. Примонтировать этот конфигурационный файл и поправить папку для веб-документов по умолчанию:

docker-nginx:
  image: nginx
  ports:
    - '8094:80'
  volumes:
    - ./:/var/www/html/
    -./nginx:/etc/nginx/conf.d
  networks:
    - losst-network

Осталось создать файл index.php и можно тестировать:

vi index.php

<?php phpinfo(); ?>

Теперь можно запускать контейнеры:

docker-compose up

 

В отличие от предыдущего раза, теперь перед запуском будет собран новый контейнер на основе файла Dockerfile. Такие контейнеры собираются только первый раз, если они не существуют. Чтобы их пересобрать используйте опцию --build:

docker-compose up --build

Теперь у вас есть полноценное веб-приложение, которое доступно на вашем компьютере, может использовать базу данных, PHP и много чего другого. Вы можете добавить любые недостающие вам контейнеры.

10. Подключение к контейнеру

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

docker-compose up -d

И используйте docker-compose exec. Подключимся к контейнеру с Nginx:

docker-compose exec docker-nginx /bin/bash

Перед вами откроется оболочка Bash этого контейнера. Устанавливать здесь что-то вручную не рекомендуется, так как всё сотрётся после удаления контейнера, но для тестирования работы чего либо такая возможность будет очень кстати.

Выводы

В этой статье мы разобрали использование docker для чайников. Тема довольно обширная и сложная, но очень интересная. Развернув таким образом проект на одной машине, вы сможете развернуть его там, где вам нужно просто скопировав туда конфигурацию. Поэтому эта технология завоевала такую большую популярность среди разработчиков и DevOps.

Ответить

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: