Docker

Проблемы с поставкой программ:

  • Программы зависят от библиотек. Иногда от конкретных версий.
  • Иногда программы опираются на особенности ОС…
  • … или размещения файлов.

Как сделать установщик для программы так, чтобы она точно заработала или хотя бы сообщила, что не так?

  • Строгие разработческие практики: отслеживание используемых зависимостей и предположений.
  • Регулярная проверка работоспособности в разных конфигурациях.
  • Автоматический анализ программ на предмет неявных зависимостей.

Зачем нужен Docker

  • Контейнеры не нужно долго настраивать, как виртуальные машины.
    Альтернатива: nix-shell.

  • Контейнер можно удалить или создать одной командой.
    Альтернатива: nix-shell.

  • Не надо мучиться при поисках/сборке библиотек.
    Альтернатива: пакетный менеджер.

  • Можно не перенастраивать сервер, если сменились требования: обновил Docker-образ — всё заработало как надо.
    Альтернативы для этого: Puppet, Ansible, Chef или решения, встроенные в механизмы оркестрации типа Kubernetes.

Контейнеры

Container (контейнер) — легковесный аналог виртуальной машины.

docker container — команды для управления контейнерами.

docker container ls --all их перечисляет.

На каждый запуск сервиса Docker создаёт новый контейнер.

Пример: docker container run -it archlinux bash ”--- запустить (run) новый контейнер, основанный на образе Arch Linux, с “сервисом” bash в терминале (-t), к которому мы тут же подключаемся интерактивно (-i).

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

Образы

Image (образ) — состояние docker-контейнера.

docker image — команды для управления образами.

docker image ls их перечисляет.

Существует коллекция docker-образов на любой вкус: https://hub.docker.com/.

У образа есть название и тег.

docker pull название:тег выкачивает образ локально.

Популярные образы

https://learn.g2.com/best-docker-containers-repository

Полезные команды

  • docker container diff C ”--- перечислить изменения, внесённые контейнером .
  • docker container commit C ”--- создать новый образ на основе состояния контейнера .
  • docker container attach C ”--- подключить свой терминал к контейнеру .
  • docker container exec C cmd ”--- выполнить команду cmd в контейнере . Её stdin и stdout подключены к вызывающей консоли.
  • docker container create I cmd ”--- создать контейнер на основе образа , выполняющий команду cmd.
  • docker run -it I ”--- интерактивно запустить команду по умолчанию в новом контейнере на основе . Мораль №1: есть команда по умолчанию; мораль №2: в некоторых командах можно опускать container или image.

Сложный пример

docker run \
  --name some-nginx \
  -v /some/content:/usr/share/nginx/html:ro \
  -p 8080:80 \
  -d \
  nginx

Запустить новый контейнер на основе образа nginx, назвать его some-nginx, дать ему доступ на чтение (ro) к директории /some/content/, которую внутри контейнера будет видно по пути /usr/share/nginx/html, пробросить порт 8080 на хостовой машине на порт 80 на гостевой; запускать в фоне (-d).

Запустится веб-сервер nginx.

(”\” ровно в конце строки в shell, C и других языках означает, что следующая строка считается продолжением данной)

Мусор

Каждый вызов docker run создаёт новый контейнер.

Если их воспринимать как черновики, то место на диске можно сберечь, если пользоваться командой docker container prune, уничтожающей остановленные контейнеры.

Dockerfile

  • Чтобы создать нетривиальный docker-образ, не стоит собирать его с нуля или вносить изменения руками и делать docker commit: так будет сложно понять, как воссоздать образ заново в случае потери или смены требований. Лучше воспользоваться Dockerfile ”--- файлом, описывающим программно, как создать образ. См. https://docs.docker.com/engine/reference/builder/.
  • Выполнение каждой команды в Dockerfile сгенерирует новый слой ”--- набор изменений относительно предыдущего слоя. Если на шаге произошла ошибка (или шаг в Dockerfile изменился), шаги не будут выполняться заново.
  • На самом деле, при создании контейнер заводит новый слой относительно своего образа, а docker commit превращает схлопывает этот слой и образ в новый образ.

Пример Dockerfile

FROM ubuntu:18.04
COPY poems /root/poems
ENV EDITOR vim
RUN apt-get update && apt-get install -y \
    git \
    vim \
    && rm -rf /var/lib/apt/lists/*
CMD $EDITOR /root/poems
  • В качестве основы взять образ ubuntu:18.04;
  • Скопировать файл poems по пути /root/poems в образе;
  • Записать vim в переменную EDITOR;
  • Установить git и vim;
  • Назначить в качестве команды по умолчанию vim /root/poems.