Время прочтения: 6 мин.

Давайте разберем последовательно термин Docker. Docker — это программное обеспечение для автоматизации развёртывания и управления приложениями в средах с поддержкой контейнеризации. © Википедия  

Осуществляя процесс автоматизации развертывания приложения, Docker может предложить пользователю следующие возможности:

  • Изоляция запущенных приложений. Можно отделить ваше приложение от ОС хоста и обращаться с ним как с управляемым приложением.
  • Облегчение процесса разработки, тестирования и развертывания приложений
  • Нет необходимости в конфигурации среды для запуска – она поставляется вместе с приложением.

Разберем эти достоинства на примерах:

  • Continuous development и zero-downtime deployment. Вы написали скрипт, которому для запуска необходимы библиотеки определенной версии, а также некое предустановленное ПО, и вы хотите поделиться результатом вашей работы с коллегами. Но увы, из-за специфичности библиотек, вашим коллегам нужно либо переустанавливать себе все необходимые либы, либо каждому выполнять у себя настройку virtualenv. А ведь ещё есть и ПО, которое необходимо установить со своими настройками конфигурации… Весь этот муторный процесс можно облегчить в разы, поставляя свой скрипт как контейнер.  Вся необходимая среда для запуска будет поставляться вместе с приложением. И коллегам будет достаточно будет выполнить одну простую команду для запуска.
  • Простота миграции. У вас есть веб-приложение с развернутым веб-сервером и серверным-приложением. При миграции, конечно же, можно заново прописывать разрешения, конфиги и настраивать среду, но проще будет опять же просто запустить подготовленный контейнер на новом инстансе, чем перенастраивать все заново.
  • Запуск небезопасного кода. Docker позволяет запускать любое ПО, в том числе графический софт, безопасно изолировав его в контейнере. Поэтому он идеально подходит для запуска разного рода недоверенного или просто небезопасного кода.

Основные понятия

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

Докер-контейнер — это некий экземпляр, «физическое воплощение» того образа, который описывает его. Из одного образа может быть создано множество контейнеров.

Есть особый класс файловых систем, которые называются Layer File System (LFS). Основная их идея заключается в том, что файловая система представляется в виде множества отдельных слоёв и результат является продуктом их объединения, можно провести аналогию с git squash.

Объединение слоёв происходит по следующим правилам:

  • Слои упорядочены, только один из них считается слоем верхнего уровня, второй и все последующие – слои нижнего уровня;
  • Доступ к объектам файловой системы осуществляется «сверху вниз». То есть мы последовательно обходим слои начиная с верхнего, и проверяем его на наличие объекта. Если же объект присутствует, то мы возвращаем его, несмотря на то, есть ли объект с таким же именем в слое пониже или нет; иначе спускаемся на слой ниже и так далее… Если же объекта нет ни в одном из слоев, то возвращается ошибка, сообщающая об этом;
  • Любые действия изменяющие текущее состояние файловой системы осуществляются на верхнем слое, не затрагивая нижние

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

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

Разберем подробнее на примере докер-образа ubuntu:15.04:

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

 Если слои образа — это множество read-only слоев, то слой контейнера — это тонкий слой, который можно использовать как для чтения, так и для записи.   То есть по сути, создание контейнера выглядит так: к слоям образа добавляем сверху слой, для которого разрешена запись. Можно сделать и обратное – зафиксировать состояние файловой системы, и сделать из контейнера образ, сделав верхний read-only.

Режимы запуска контейнеров

Существуют различные режимы запуска контейнеров:

  • Программа (режим «По умолчанию»), в этом случае точкой входа в контейнер является некий скрипт. Контейнер запускается вместе с ним и после того, как скрипт завершает свою работу контейнер останавливается.

Пример:

docker run –-rm my_container_program

Здесь мы создаем контейнер на основе образа my_container_program

Ключ —rm при запуске означает, что после исполнения скрипта, контейнер будет удален

  • Демон (ключ -d), запуск программ, которые работают как сервис и не требуют прямого управления. Например, таким образом в контейнере можно запускать базы данных, веб-сервера.

Пример:

docker run –p 80:80 –d –name service_cont service_img

Запускаем контейнер в виде демона(ключ –d) на основе образа service_img

Ключ —name позволяет задать контейнеру имя, здесь это service_cont

Ключ –p это сопоставление портов докер-контейнера портам на хост-системе. В данном случае мы сопоставим 80 порты.

  • Интерактивный (ключ -it), можно подключить интерпретатор команд shell и взаимодействовать с контейнером в режиме командной строки

Пример:

docker run –it ubuntu:18.04

Запуск контейнера на основе образа Ubuntu:18.04 в интерактивном режиме.

Более подробно можно прочесть о запуске контейнеров в документации: (https://docs.docker.com/engine/reference/run/)

Контейнеризация и отличие от VM

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

VM Docker
Аппаратная виртуализация Виртуализация на уровне операционной системы
Каждой машине соответствует отдельная операционная система Контейнеры работают как отдельный процесс на хосте, разделяя ядро системы
Есть возможность распределить между собой ресурсы хоста: процессор, оперативную память, дисковое пространство С помощью cgroups можно ограничить отдельно каждый
контейнер в потреблении ресурсов
Линейный расход дискового пространства, каждой машине необходимо место для гостевой операционной системы Layed File System позволяет сэкономить место на диске,
за счет повторного использования слоев
  Файловую систему одного образа, можно использовать
в качестве основы для формирования новых образов

Сегодня я описал Docker и рассказал про его основные преимущества. Разобрал основные различия с VM (virtual machine), а также описал различные режимы запуска контейнеров. В следующей статье я на примерах покажу различные способы взаимодействия контейнеров, как с операционной системой хоста, так и друг с другом.