UMGUM.COM 

Инсталляция Docker ( Развёртывание в linux-е подсистем "Docker" и управляющего скрипта "Docker Compose" )

3 мая 2019  (обновлено 1 мая 2021)

OS: "Linux Debian 8/9/10", "Linux Ubuntu 16/18/20".
Apps: "Docker", "Docker Compose".

Задача: развёртывание в linux-е системы контейнеризации "Docker" вкупе со скриптом управления таковой "Docker Compose". Никаких сложностей, но делается так часто, что проще вынести описание отдельно и ссылаться на него при необходимости.

Одно из клёвейших открытий последних последних лет для меня - "Docker". Это программное обеспечение для автоматизации развёртывания и управления приложениями в средах с поддержкой контейнеризации, позволяющее "упаковать" приложение со всем его окружением и зависимостями в контейнер, который может быть применён на любой современной Linux-системе с поддержкой "cgroups" в ядре и изоляцией "пространств имён (namespaces)".

Написан на языке "Go". Изначально использовал возможности LXC, с 2015 года применял собственную библиотеку, абстрагирующую виртуализационные возможности ядра Linux - "libcontainer". С появлением "Open Container Initiative" начался переход от монолитной к модульной архитектуре.

Для экономии дискового пространства проект использует файловую систему "Aufs" с поддержкой технологии каскадно-объединённого монтирования: контейнеры используют образ базовой операционной системы, а изменения записываются в отдельную область. Также поддерживается размещение контейнеров в файловой системе "Btrfs" с включённым режимом копирования при записи.


В состав программных средств входит сервер контроля контейнеров "docker" и сервер запуска контейнеров как таковых "containerd", а также клиентские средства, позволяющие из интерфейса командной строки управлять образами и контейнерами (включая API, позволяющий в стиле REST управлять компонентами программно).

Инструментарием "Docker"-а обеспечивается полная изоляция запускаемых контейнеров на уровне файловой системы (у каждого контейнера собственная корневая файловая система), на уровне процессов (процессы имеют доступ только к собственной файловой системе контейнера, а ресурсы разделены средствами "libcontainer"), на уровне сети (каждый контейнер имеет доступ только к привязанному к нему сетевому "пространству имён" и соответствующим виртуальным сетевым интерфейсам).

Установка системы контейнеризации приложений "Docker".

По состоянию на начало 2021-го несколько поколений "Docker" стали устаревшими и неподдерживаемыми: их дистрибутивы как правило называются "docker", "docker.io" или "docker-engine". Есть смысл профилактически зачистить систему от них:

# apt-get remove docker docker-engine docker.io containerd runc

Данные, по умолчанию располагающиеся в "/var/lib/docker/", могут быть наследованы новыми версиями, возможно с их автоматической конвертацией под следующие мажорные релизы.

Современный "Docker" выпускается в двух вариантах: "Community Edition" (бесплатная) и "Enterprise Edition" (проприетарная, платная). Мы будем работать со свободно распространяемым дистрибутивом, именуемым в APT-системе "docker-ce".

В централизованных репозиториях стабильных версий "Debian/Ubuntu" актуальные пакеты "Docker" отсутствуют - оно и понятно, технология переднего края, непрерывно развивающаяся. Единственный простой способ добычи дистрибутива в подключении репозитория разработчиков и установке оттуда.

Установим утилиты, необходимые для ручного подключения дополнительных APT-репозиториев:

# apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common

Перед подключением нового APT-репозитория скачаем и применим PGP-ключ, которым подписано содержимое репозитория:

# curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -

Создаём выделенный конфигурационный файл с описанием подключаемого APT-репозитория:

# echo -e "# Official APT-repository Docker-CE\ndeb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable" >> /etc/apt/sources.list.d/docker.list

Обновляем сведения о доступном программном обеспечении и устанавливаем базовый набор подсистем "Docker":

# apt-get update && apt-get install docker-ce docker-ce-cli containerd.io

Обращаю внимание на то, что в качестве прослойки абстракции связей контейнеров "Docker-CE" с ядром "Linux" сейчас используется открытая реализация "Open Container Initiative (containerd.io)", сменившая использовавшуюся в предыдущем поколении "Docker" самодельную подсистему "docker-containerd".

Конечно, при остром желании можно установить "Docker" из DEB-пакетов, скачав их из официального хранилища дистрибутивов, потеряв при этом удобства автоматического обновления.

Сразу после установки "Docker" автоматически будут запущены два основных сервиса, о которых далее.

Прослойка изоляции и абстракции ("cgroups" и "namespaces", а также "aufs|btrfs") между ядром "Linux" и docker-контейнерами:

# systemctl status containerd.service

Централизованный сервис управления "виртуальными контейнерами" как таковыми:

# systemctl status docker.service

Система контейнеризации "Docker" вполне управляема непривилегированным пользователем - для этого достаточно включить его в специализированную группу "docker":

# usermod --append --groups docker username

Установка утилиты автоматизации запуска docker-контейнеров "Docker Compose".

Утилита "Docker Compose" написана на языке "Python" и представляет собой единственный файл-скрипт (размером в 16MB), обрабатывающий передаваемый ему конфигурационный YAML-файл и взаимодействующий с "Docker (engine)". Установка тривиальна и заключается в загрузке файла.

Утилита пока не вышла на уровень, когда какой-то из версий можно задать статус "stable" или "latest" - так что первым делом есть смысл сходить на сайт разработчиков, поискать прямую ссылку на последний проверенный релиз и уже его загружать:

# curl -L "https://github.com/docker/compose/releases/download/1.28.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose

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

# ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Лучше сразу проверить, запускается ли утилита (попутно убедимся, что интерпретатор "Python" присутствует в операционной системе):

$ docker-compose --version

Автоматизация представления как файлов журналов docker-контейнеров.

Как правило, docker-образы принято собирать таким образом, чтобы журналы событий контейнеризированного приложения перенаправлялись в терминальные потоки STDOUT и STDERR, которые автоматически, посредством "logging driver", оказываются доступны для просмотра снаружи docker-контейнера через команду "docker logs".

Когда docker-контейнеров немного, их журналы событий можно выводить в текстовые файлы сопутствующими командами в скриптах запуска, например таким образом:

# docker logs --follow example-app > /var/log/docker/output-example-app.log 2>&1 &

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

# vi /usr/local/bin/docker-logs-collector.sh && chmod +x /usr/local/bin/docker-logs-collector.sh

#!/bin/bash

# Exit if another instance of this script is running
for PID in $(pidof -x `basename $0`) ; do [[ "${PID}" != "$$" ]] && exit 1 ; done

# Endless waiting accessibility "Docker Engine"
while true ; do

  # Monitor containers startup and capture event logs output to a files
  DOCKER_LOGS="/var/log/docker" ; [ -d "${DOCKER_LOGS}" ] || mkdir -p "${DOCKER_LOGS}"
  docker events --filter 'event=start' --format '{{.Actor.Attributes.name}}' | \
  while read NAME ; do
    docker logs --follow "${NAME}" > "${DOCKER_LOGS}/docker-output-${NAME}.log" 2>&1 &
  done
  sleep 10
done

Запуск скрипта вручную, с отрывом его от текущей терминальной сессии:

# /usr/local/bin/docker-logs-collector.sh &

Нужно сделать так, чтобы скрипт автоматизации сбора журналов запускался автоматически после старта операционной системы и подсистемы контейнеризации "Docker". Ранее это делалось через скрипты "/etc/rc.local" подсистемы "System-V", но ныне принято решать такие задачи через регистрацию короткоживущей службы "Systemd".

# vi /etc/systemd/system/docker-logs-collector.service

[Unit]
Description=Service script of collecting logs and presenting them as files
Requires=docker.service containerd.service
After=docker.service

[Service]
ExecStart=/usr/local/bin/docker-logs-collector.sh &
ExecReload=/usr/local/bin/docker-logs-collector.sh &
Restart=/usr/local/bin/docker-logs-collector.sh &
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=default.target

Указываем "Systemd" перечитать и принять новую конфигурацию, а потом явно активируем и запускаем новый сервис:

# systemctl daemon-reload
# systemctl enable docker-logs-collector.service
# systemctl start docker-logs-collector

Специально заниматься ротацией полученных от docker-контейнеров файлов журналов не вижу смысла, так как обычно они не разрастаются до катастрофических размеров, зачищаясь автоматически при пересоздании docker-контейнера - мы не приращиваем наши текстовые файлы журналов, а лишь воспроизводим в удобном виде те данные, что уже имеются в журнале docker-подсистемы.


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )