Перейти к содержанию

▍Docker и Docker Compose

Docker Logo

Установка Docker и Docker Compose в Ubuntu 22.04

Чтобы установить Docker на Ubuntu, выполним подготовительные действия. Для начала, обновим состав установочных пакетов, чтобы иметь представление об их актуальных версиях:

sudo apt update

Предварительно установим набор пакетов, необходимый для доступа к репозиториям по протоколу HTTPS:

apt-transport-https — активирует передачу файлов и данных через https;
ca-сertificates — активирует проверку сертификаты безопасности;
curl — утилита для обращения к веб-ресурсам;
software-properties-common — активирует возможность использования скриптов для управления программным обеспечением.
sudo apt install apt-transport-https ca-certificates curl software-properties-common

Далее добавим в систему GPG-ключ для работы с официальным репозиторием Docker:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

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

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Повторно обновим данные о пакетах операционной системы:

sudo apt update
Приступаем к установке пакета Docker.

sudo apt install docker-ce -y

После завершения установки запустим демон Docker и добавим его в автозагрузку:

sudo systemctl start docker

sudo systemctl enable docker

Добавим пользователя в группу docker, чтобы каждый раз не вводить sudo для выполнения Docker команд.

sudo usermod -aG docker ${USER}
На этом установка Docker завершена и можно начинать с ним работу.

Установка Docker Compose на Ubuntu

Docker Compose — это инструмент для описания и запуска мультиконтейнерных приложений Docker. Инструмент позволяет пользователям запускать, выполнять, общаться и закрывать контейнеры с помощью одной команды.

Посмотрим последнюю сборку Docker Compose в репозитории на Github и загрузим ее при помощи утилиты curl со следующими параметрами:

–L разрешает редиректы, если файл перемещен;
–o модифицирует имя файла для удобства его запуска и указывает каталог для сохранения.

sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
После завершения загрузки, добавим загруженному бинарному файлу права на выполнение:
sudo chmod +x /usr/local/bin/docker-compose

Заметим, что выполнить установку Docker Compose можно было из репозитория Ubuntu командой sudo apt-get install docker-compose. Однако, в репозитории может быть не самая последняя версия. Способ, который мы описали выше, позволит загрузить актуальную версию утилиты Docker Compose.

Чтобы проверить корректность работы утилиты, выполним проверку ее версии:

docker-compose --version
Если команда вернула номер версии, значит Docker Compose готов к работе.

Когда нужно удалить Docker Compose, достаточно выполнить команду удаления файла:

sudo rm /usr/local/bin/docker-compose

Если установка выполнялась через пакетный менеджер apt, нужно его вызвать с параметром purge:

sudo apt purge docker-compose

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

sudo apt autoremove

Полезные команды по работе с Docker

Принудительно зайти в шел контейнера

docker run --entrypoint "" --rm -it testconteiner:latest sh

Вывести под каким пользователем запущен контейнер

docker inspect $(docker ps -q) --format '{{.Config.User}} {{.Name}}'

Найти имя контейнера по имени каталога

docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Id}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}}'
Docker overlay2

Вывести внутренние IP контейнеров

docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
Docker IP

Сканирование образа Docker на наличие известных уязвимостей с помощью Snuk

Для начала нам нужно получить токен, соотвественно регистрируемся на сайте Snuk, переходим в раздел "Account Settings" и нажимаем на строку "click to show" под пунктом "Key".

Snyk

Запускаем команду сканирования:

docker run --rm -it --env SNYK_TOKEN=ваш_токен -v /var/run/docker.sock:/var/run/docker.sock snyk/snyk:docker snyk test --docker nginx

где nginx - имя контейнера, который нужно проверить.

Чистим Docker от мусора

Было:

$ docker system df

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          149       38        33.72GB   22.49GB (66%)
Containers      58        51        924.2MB   791.6MB (85%)
Local Volumes   282       0         231MB     231MB (100%)
Build Cache     0         0         0B        0B

Это удалит все что больше не нужно, и не затронет запущенные контейнеры и нужные имеджи.

docker system prune -a

Стало:

$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          38        36        13.67GB   733.3MB (5%)
Containers      51        51        132.6MB   0B (0%)
Local Volumes   282       0         231.9MB   231.9MB (100%)
Build Cache     0         0         0B        0B

Ограничение логирования

sudo nano /etc/docker/daemon.json
{
  "storage-driver": "btrfs",
  "live-restore": true,
  "ipv6": false,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
параметр live-restore отвечает за то, чтобы контейнеры продолжали работать, если демон становится недоступным, т.к. по умолчанию, когда демон Docker завершает работу, он останавливает работающие контейнеры. Параметр оперативного восстановления помогает сократить время простоя контейнера из-за сбоев демона, плановых простоев или обновлений.

Выгрузка, загрузка и распространение образов контейнеров Docker в виде архива

Сохранение образа в архив

Для начала рассмотрим как можно выполнить сохранение образа контейнера из среды. Для выполнения данной операции используется команда docker save (man docker-save):

docker pull ubuntu:18.04
docker save -o ubuntu-1804.tar ubuntu:18.04
После выполнения данной команды образ со всеми слоями будет выгружен из пространства образов демона Docker в файловую систему в виде архива tar.

Интересно, что таким образом можно выгрузить более одного образа:

docker pull ubuntu:16.04
docker save -o ubuntu-16+18.tar ubuntu:18.04 ubuntu:16.04
Таким образом, вы можете за одну команду выгрузить все необходимые для распространения контейнеры в один tar-архив.

Загрузка образа в среду Docker

Для выполнения загрузки ипользуется обратная операция docker load:

# удалим образы
docker rmi ubuntu:18.04 ubuntu:16.04
# убедимся, что нет доступных образов
docker images | grep ubuntu | wc -l
# загрузим образы из архива в среду Docker
docker load -i ubuntu-16+18.tar 
aa54c2bc1229: Loading layer [==================================================>]  121.6MB/121.6MB
7dd604ffa87f: Loading layer [==================================================>]  15.87kB/15.87kB
2f0d1e8214b2: Loading layer [==================================================>]  11.78kB/11.78kB
297fd071ca2f: Loading layer [==================================================>]  3.072kB/3.072kB
Loaded image: ubuntu:16.04
Loaded image: ubuntu:18.04
# проверим доступное количество образов
docker images | grep ubuntu | wc -l
2

Таким образом вы можете распространять образы контейнеров Docker между узлами без использования реестра и даже сети, например, на DVD или накопителе USB.

Отличия Save, Load от Export, Import

Docker поддерживает команды export и import, которые часто могут быть перепутаны с save, load. Ключевое отличие данных команд в том, для чего они предназначены:

  • save/load выгружают и загружают образы контейнеров, которые будут использоваться для создания контейнеров;
  • export выгружает файловую систему созданного контейнера (не образ контейнера, а изменения, которые внес контейнер в образ);
  • import позволяет создать образ тома файловой системы из архива, созданного с помощью export, который может использоваться, например, при запуске контейнера с помощью --volumes-from.

В целом, разница заключается, что save/load относятся к данным образов, а export/import к данным контейнеров.

Docker-in-Docker

Проблемы:

  • Первая проблема касается LSM (модулей безопасности Linux), таких как AppArmor и SELinux: при запуске контейнера «внутренний Docker“ может попытаться применить профили безопасности, которые будут конфликтовать или запутывать "внешний Docker".
  • Вторая проблема связана с драйверами хранилища Docker. Когда вы запускаете Docker-in-Docker, внешний Docker работает поверх обычной файловой системы (EXT4, BTRFS или любой другой, которой вы располагаете), а внутренний Docker работает поверх системы копирования при записи (AUFS, BTRFS, Device Mapper и т. д., в зависимости от того, что настроен использовать внешний Docker). При этом возникает множество комбинаций, которые не будут работать. Например, вы не сможете запускать AUFS поверх AUFS.

Решение:

Когда вы запускаете свой CI-контейнер (Jenkins или другой), вместо того, чтобы взламывать что-то вместе с Docker-in-Docker, начните его со строки:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

Теперь этот контейнер будет иметь доступ к сокету Docker и, следовательно, сможет запускать контейнеры. За исключением того, что вместо запуска "дочерних" контейнеров он будет запускать "родственные" контейнеры. Это выглядит и работает как Docker-in-Docker, но это не Docker-in-Docker: когда этот контейнер будет создавать дополнительные контейнеры, они будут созданы в Docker высшего уровня. Вы не будете испытывать побочных эффектов вложенности, и кэш сборки будет совместно использоваться для нескольких вызовов.

К началу