itmo_conspects

Лекция 2. Контейнеризация

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

Механизмы контейнеризации

Этими механизмами являются пространства имен и контрольные группы:

С помощью пространств имен можно изолировать процессы друг от друга. Для этого существует 8 пространств имен:

  1. Cgroup - изолирует корневую директорию контрольных групп, чтобы процесс в контейнере видел свою иерархию контрольных групп.
  2. IPC (от Inter-Process Communication) - изолирует ресурсы для межпроцессного взаимодействия (такие как очереди сообщений или разделяемая память)
  3. Network - изолирует сетевые устройства, стеки, порты и таблицы маршрутизации
  4. Mount - изолирует точки монтирования файловых систем
  5. PID (от Process ID) изолирует пространство идентификаторов процессов. Процесс внутри контейнера видит только свои процессы и считает, что его идентификатор равен 1, а не реальному идентификатору на хосте
  6. Time - изолирует системное время, позволяя контейнеру иметь своё представление о времени (появилось в Linux 5.6)
  7. User - изолирует идентификаторы пользователей и групп, что позволяет процессу в контейнере быть пользователем root внутри контейнера
  8. UTS (от UNIX Time-Sharing System) - изолирует имена хоста и домена NIS (Network Information Service, системы для распространения конфигурации между несколькими узлами)

Пространства имен можно создавать с помощью утилиты unshare:

sudo unshare --uts /bin/bash

Оболочка Bash запуститься в окружении в изолированном пространстве UTS. Для создания пространств имен используются флаги --ipc, --mount, --net, --pid, --uts, --user, --cgroup, --time

Для создания контейнеров интересны три пространства: PID, Network и Mount

Чтобы ограничивать ресурсы процессора, ОЗУ, ПЗУ и прочего, используется механизм контрольных групп. Для создания контрольных групп есть три способа:

Работа с Docker

В Docker управлением контейнерами занимается демон containerd. Этот демон управляется утилитой командной строки docker-cli

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

Образы можно создавать, а можно использовать готовые образы из репозитория, которые включают нужное приложение. Чтобы запустить образ, используется команда:

docker run hello-world

Здесь hello-world - минимальный образ, который был загружен из репозитория Docker Hub (https://hub.docker.com/_/hello-world). При запуске запускается контейнер, который выводит обучающую информацию о Docker

Чтобы создать образ, используется Dockerfile - специальный файл, который описывает создание образа. Например, для hello-world файл Dockerfile выглядит так:

FROM scratch
COPY hello /
CMD ["/hello"]

Здесь инструкциями указано, что:

  1. Образ основан на другом образе scratch (который представляет из себя пустой образ)
  2. Далее копируется исполняемый файл hello в корень контейнера
  3. А затем запускается команда /hello

В Dockerfile также могут использоваться другие команды (*тык*)

Далее используется команда:

docker build -t hello-world:v1 .

Здесь hello-world:v1 - это имя и версия образа, а . - корневой путь контейнера, относительно которого выполняются команды в Dockerfile. По умолчанию docker build будет искать файл ./Dockerfile, но можно указать флагом -f ./otherfolder/Dockerfile другое местоположение

Чтобы узнать список загруженных и созданных образов, используется команда docker images:

IMAGE                ID           DISK USAGE   CONTENT SIZE   EXTRA
hello-world:latest   5e2309035332     25.9kB         9.49kB    U

Здесь указаны идентификатор образа и объем на диске

Команда docker image inspect <image-name>:<version> позволяет изучить образ:

docker image inspect

Сам образ представляет из себя слои. Каждая инструкция в Dockerfile представляет слой, который описывает изменения файловой системы в образе. Далее после применения инструкции из Dockerfile запоминается хеш слоя

Если какая-либо команда в Dockerfile изменилась, то Docker берет предыдущий слой, на основе которого собирает новый образ. При запуске контейнера весь образ остается в режиме “только для чтения” - последующие изменения файлов в ходе работы контейнера сохраняются в слое контейнера, а при чтении используется механизм объединенной файловой системы

Далее образ можно запустить:

docker run -d -p 8000:80 --name <container-name> <image-name>

Здесь применены флаги: