Принципы работы контейнеров Docker

Завершено

Ранее вы обнаружили, что контейнер становится единицей, которую вы будете использовать для распространения приложений. Вы также узнали, что контейнер используется в стандартном формате как для разработчиков, так и для групп операций.

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

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

Управление контейнерами Docker

Контейнер Docker имеет жизненный цикл, который можно использовать для управления состоянием контейнера и отслеживания его состояния.

Diagram that shows the lifecycle of a container and the transition between the lifecycle phases.

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

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

Чтобы приостановить выполнение контейнера, используйте команду приостановки. Эта команда приостанавливает все процессы в контейнере.

Чтобы остановить запущенный контейнер, используйте команду stop . Команда stop позволяет корректно завершить выполняющийся процесс, отправив ему сигнал завершения. Работа ядра контейнера прекращается после завершения процесса.

Если необходимо завершить контейнер, используйте команду kill для отправки сигнала о убийстве. Ядро контейнера захватывает сигнал убийства, но запущенный процесс не выполняется. Эта команда принудительно завершает рабочий процесс в контейнере.

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

Просмотр доступных контейнеров

Чтобы вывести список выполняющихся контейнеров, выполните команду docker ps. Чтобы просмотреть все контейнеры во всех состояниях, передайте аргумент -a.

Приведем пример:

docker ps -a

Ниже приведены выходные данные из этой команды:

CONTAINER ID    IMAGE        COMMAND         CREATED       STATUS           PORTS        NAMES
d93d40cc1ce9    tmp-ubuntu:latest  "dotnet website.dll …"  6 seconds ago    Up 5 seconds        8080/tcp      happy_wilbur
33a6cf71f7c1    tmp-ubuntu:latest  "dotnet website.dll …"  2 hours ago     Exited (0) 9 seconds ago            adoring_borg

В предыдущих выходных данных есть три элемента:

  • Имя образа, указанное в столбце IMAGE . В этом примере tmp-ubuntu: последняя версия. Обратите внимание, что из одного и того же образа можно создать несколько контейнеров. Это мощный компонент управления, который можно использовать для включения масштабирования в решениях.

  • Состояние контейнера, указанное в столбце STATUS . В этом примере у вас есть один контейнер, который выполняется, и один контейнер, который завершил работу. Состояние контейнера обычно является первым индикатором работоспособности контейнера.

  • Имя контейнера, указанное в столбце NAME . Помимо идентификатора контейнера в первом столбце контейнеры также получают имя. В данном примере имена контейнеров не были указаны явно, поэтому платформа Docker присвоила этому контейнеру произвольное имя. Чтобы предоставить контейнеру явное имя с помощью флага --name , используйте run команду.

Зачем присваивать контейнерам имена?

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

Запуск контейнера

Чтобы запустить контейнер, используйте docker run команду. Для запуска контейнера из образа достаточно просто указать его имя или идентификатор. Запущенный таким образом контейнер предоставляет интерактивный интерфейс.

Здесь для запуска контейнера с веб-сайтом в фоновом режиме следует добавить флаг -d.

docker run -d tmp-ubuntu

В этом случае команда возвращает только идентификатор нового контейнера.

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

Приостановка контейнера

Чтобы приостановить контейнер, выполните команду docker pause. Приведем пример:

docker pause happy_wilbur

Приостановка работы контейнера приостанавливает все процессы. Эта команда позволяет контейнеру продолжить процессы в дальнейшем. Команда docker unpause отменяет приостановку всех процессов в указанных контейнерах.

Перезапуск контейнера

Чтобы перезапустить контейнеры, выполните команду docker restart. Приведем пример:

docker restart happy_wilbur

Контейнер получает команду остановки, за которой следует команда запуска. Если контейнер не отвечает на команду stop, отправляется сигнал уничтожения.

Остановка контейнера

Чтобы остановить выполняющийся контейнер, выполните команду docker stop. Приведем пример:

docker stop happy_wilbur

Команда stop отправляет сигнал завершения контейнеру и процессам, выполняемым в контейнере.

Удаление контейнера

Чтобы удалить контейнер, выполните команду docker rm. Приведем пример:

docker rm happy_wilbur

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

Конфигурация хранилища контейнера Docker

Как описано ранее, всегда учитывайте контейнеры как временные, когда приложение в контейнере должно хранить данные.

Предположим, что портал отслеживания создает файл журнала в вложенной папке в корне приложения; то есть непосредственно в файловую систему контейнера. Когда приложение записывает данные в файл журнала, система записывает данные в доступный для записи слой контейнера.

Несмотря на то, что этот подход работает, к сожалению, имеет несколько недостатков.

  • Хранилище контейнеров является временным.

    Файл журнала не передается из одного экземпляра контейнера в другой. Например, предположим, что вы останавливаете и удаляете контейнер. При запуске нового экземпляра контейнера новый экземпляр основывается на указанном образе, и все предыдущие данные будут отсутствуют. Помните, что при удалении контейнера все данные в нем также уничтожаются.

  • Хранилище контейнеров связано с базовым компьютером узла.

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

  • Диски хранилища контейнеров являются менее производительными.

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

Контейнеры могут использовать два варианта для сохранения данных. Первый вариант — тома, а второй — подключения с привязкой.

Что такое том?

Том хранится в файловой системе узла в определенной папке. Выберите папку, в которой вы знаете, что данные не будут изменены процессами, отличными от Docker.

Docker создает том и управляет им с помощью команды docker volume create. Эта команда может быть частью определения Dockerfile, что означает, что вы можете создавать тома в рамках процесса создания контейнера. Docker создаст том, если он еще не существует, при первой попытке подключить том к контейнеру.

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

Несколько контейнеров могут одновременно использовать одни и те же тома. Когда контейнер перестает использовать том, он не удаляется автоматически.

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

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

Что такое подключение с привязкой?

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

Функциональность подключений с привязкой по сравнению с томами ограничена. Несмотря на то, что их производительность выше, они зависят от наличия определенной структуры папок в узле.

Тома считаются предпочтительной стратегией хранения данных для использования с контейнерами.

Для контейнеров Windows доступен еще один вариант: вы можете подключить путь S МБ в качестве тома и представить его контейнерам. Это позволяет контейнерам на разных узлах использовать одно и то же постоянное хранилище.

Конфигурация сети для контейнера Docker

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

Docker предоставляет различные параметры сети для Linux и Windows.

Для Linux существует шесть предварительно настроенных параметров сети:

  • Мост
  • Хост
  • Наложение
  • IPvLan
  • MACvLan
  • нет

Для Windows существует шесть предварительно настроенных параметров сети:

  • NAT (преобразование сетевых адресов)
  • Прозрачный режим
  • Наложение
  • L2Bridge
  • L2Tunnel
  • нет

Вы можете выбрать, какие из этих конфигураций сети будут применяться к контейнеру в зависимости от требований к сети.

Что такое сеть типа "мост"?

Сеть типа "мост" — это конфигурация, применяемая по умолчанию к контейнерам при запуске, если иная конфигурация сети не указана. Эта сеть является внутренней частной сетью, используемой контейнером, и она изолирует сеть контейнеров от сети узлов Docker.

Каждому контейнеру в сети моста присваивается IP-адрес и маска подсети, а имя узла по умолчанию — имя контейнера. Контейнеры, подключенные к сети моста по умолчанию, могут получить доступ к другим контейнерам, подключенным к мосту, по IP-адресу. Сеть типа "мост" не разрешает обмен данными между контейнерами с помощью имен узлов.

По умолчанию Docker не публикует порты контейнеров. Для включения сопоставления портов контейнеров и портов узла Docker используется флаг --publish порта Docker.

Флаг publish фактически настраивает правило брандмауэра, которое сопоставляет порты.

В данном примере портал отслеживания доступен клиентам через порт 80. Порт 80 контейнера необходимо сопоставить с доступным портом узла. На узле открыт порт 8080, который позволяет задать флаг следующим образом:

--publish 8080:80

Любой клиент, переходящий по IP-адресу узла Docker через порт 8080, сможет получить доступ к порталу отслеживания.

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

Что такое сеть узла?

Такая конфигурация позволяет запускать контейнер непосредственно в сети узла. Она фактически устраняет изоляцию между узлом и контейнером на сетевом уровне.

В данном примере предположим, что вы решили изменить конфигурацию сети и настроить сеть узла. Портал отслеживания по-прежнему доступен по IP-адресу узла. Теперь можно использовать хорошо известный порт 80 вместо сопоставленного порта.

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

В Windows сеть узлов недоступна. На узлах Windows нет возможности совместно использовать один и тот же IP-адрес (сетевой стек) между узлом и контейнером. Сеть NAT работает так же, как сеть моста, а параметр "Наложение" предоставляет IP-адрес контейнеру из той же сети, что и узел, но не тот же IP-адрес.

Наложение и другие сетевые параметры

Для более сложных сценариев в Linux и Windows предоставляются дополнительные сетевые параметры. Например, параметр наложения создает виртуальный коммутатор из сети узла, поэтому контейнеры в этой сети могут получать IP-адреса с DHCP-серверов или работать с IP-адресами из этого сетевого сегмента. Кроме того, Docker позволяет сторонним поставщикам создавать сетевые подключаемые модули.

Что такое сеть "нет"?

Чтобы отключить сеть для контейнеров, используйте параметр none network. Это может быть полезно, если у вас есть приложение, которое не использует сеть, или если вы просто хотите проверить, работает ли приложение должным образом в контейнере.

Рекомендации по операционной системе

Имейте в виду, что существуют различия между операционными системами настольных компьютеров для параметров конфигурации сети Docker. Например, сетевой интерфейс Docker0 недоступен в macOS при использовании сети моста и использование конфигурации сети узла не поддерживается как для настольных компьютеров Windows, так и для macOS.

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

Проверьте свои знания

1.

Контейнер запускается с помощью флага --publish 8080:80. Какая из следующих конфигураций сети, вероятнее всего, используется для контейнера?

2.

Какой вариант хранилища является наилучшим, если узел и контейнер должны совместно использовать файл для управления разрешением сервера имен, например файл resolve.conf в Linux?