October 7, 2022

Docker - устройство и принципы работы

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

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

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

Что такое Docker?

Docker — популярная технология контейнеризации, появившаяся в 2013 году. Тогда одноименная компания предложила способ виртуализации ОС, при котором код приложения, среда запуска, библиотеки и зависимости упаковываются в единую «капсулу» — контейнер Docker.

Одной из реализаций идеи о разделении ресурсов стали Croot jail и операция Chroot, которые появились в 1979 году в UNIX версии 7. С помощью Chroot jail процесс и его дочерние элементы изолировались от основной ОС. Docker фактически можно считать продолжением этой идеи. Но корневой процесс мог выходить из chroot, а механизмов безопасности на тот момент еще не придумали.
Спустя 20 лет появился FreeBSD Jail — механизм виртуализации, позволяющий внутри одной ОС использовать несколько изолированных систем, которые назвали тюрьмами. Далее технологии контейнеризации развивались стремительно. В 2001 году появился Linux VServer, который использовал chroot-подобную утилиту и применялся для безопасного разделения ресурсов. Каждый раздел назывался «контекстом безопасности», а виртуализированная система внутри него — виртуальным частным сервером.
В 2005 году представили OpenVZ с виртуализацией на уровне ОС, благодаря которой усовершенствовалась технология изоляции. Но был и серьезный недостаток: у контейнеров и хоста была одна архитектура и версия ядра. Если требовалась другая, возникали проблемы.
В 2007 году компания Google представила функцию CGroups, ограничивающую использование ресурсов (CPU, ROM, дисковый ввод-вывод, сеть и т. д.) на уровне групп процессов. Спустя год выпустили Linux Containers (LXC), который имел много общего с OpenVZ и Linux-VServer, но использовал механизмы namespaces и CGroups из Linux-ядра вместо сторонних механизмов, внедряемых в ядро с помощью патчей.
В 2013 году компания Cloud Foundry создала Warden. Новая утилитапредназначалась для запуска приложений, которые получают все свои зависимости от частей ПО, называемых buildpacks. Контейнеры Warden обычно имеют два слоя: слой только для чтения с корневой файловой системой ОС и неперсистентный слой чтения/записи самого приложения и его зависимостей. В 2013 году на рынке появился и Docker.

Для чего вообще нужен docker контейнер?

Обычно, во время разработки, для каждого проекта вы настраиваете своё окружение. Но вот произошла такая ситуация: что-то случилось с вашим компьютером и приходится переустанавливать операционную систему(ОС). Соответственно, чтобы запустить ваш проект, необходимо настраивать окружение заново. Бывает ещё гигантское количество ситуаций, которые сводятся к одной проблеме - настройка окружения для разработки. Так вот Docker - коробка, которую достаточно единожды настроить под проект, чтобы в дальнейшем не было проблем с эксплуатацией/расширением сервиса.

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

Чем контейнеризация отличается от виртуализации?

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

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

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

Docker и виртуальные машины не очень хорошо сочетаются друг с другом. Да, иногда в продакшене сервер нарезают на виртуалки и в них запускают контейнеры. Но такая схема, с двойной виртуализацией, приводит к избыточному расходу ресурсов. Её часто критикуют, и, надо признаться, по делу. Если в компании всё же сложилась такая практика, вместо гипервизора можно поставить Kubernetes, который будет устанавливать приложения напрямую на железо.

Давайте рассмотрим особенности контейнеров.

Особенности контейнеров

  • Важнейшая особенность контейнеров — их сравнительно короткий жизненный цикл. Любой контейнер можно остановить, перезапустить или уничтожить, если это необходимо. Данные, которые содержатся в контейнере, при этом тоже пропадут. Так выработалось правило проектирования приложений: не хранить важные данные в контейнере. Такой подход называют Stateless.
  • Объем контейнеров измеряется в мегабайтах, поскольку в них упаковывают лишь те процессы и зависимости ОС, которые необходимы для выполнения кода. Легковесные контейнеры быстро запускаются и экономят место на диске.
  • Один контейнер соответствует одному запущенному процессу. Отключение отдельного контейнера для отладки или обновления никак не помешает нормальной работе всего приложения.
  • Контейнеризация обеспечивает надежную изоляцию процессов и повышает уровень безопасности систем. Приложения, которые работают внутри контейнера, не имеют доступа к основной ОС и не могут на неё влиять.
  • Благодаря контейнерам можно автоматизировать развертывание приложений на разных хостах.
  • Использование контейнеров позволяет перейти с монолита на микросервисную архитектуру. За счет этого ускоряется разработка новой функциональности, поскольку нет опасений, что изменения в одной компоненте затронут всю остальную систему.
  • С точки зрения эффективности контейнеры котируются выше виртуальных машин. На одинаковом оборудовании можно запустить большое количество контейнеров, тогда как ВМ будет в разы меньше. Это важно при использовании облачной инфраструктуры — потребуется меньше ресурсов.

Преимущества использования Docker

Какие преимущества Docker приносит компаниям и разработчикам?

  1. Гибкость и адаптивность. Благодаря Docker можно легко запускать контейнер в облачной инфраструктуре и на любом локальном устройстве. Можно создать базовые шаблоны контейнеров и использовать повторно бесконечное число раз. Бесшовная переносимость и простота развертывания — важные преимущества этой технологии.
  2. Меньше ошибок и несовпадений окружений. В контейнерах Docker содержится всё, что требуется для запуска приложения, поэтому перенос приложений из одной среды в другую не вызывает затруднений. Исчезает проблема, когда у разработчиков всё функционирует как надо, а на боевом сервере — нет.
  3. Скорость развертывания. Так как настраивать окружение для разработки, тестирования и боевого режима больше не нужно, время развертывания сокращается в несколько раз.
  4. Рост универсальности. Docker позволяет использовать любые языки программирования и стек технологий на сервере, избавляя от проблемы несовместимости разных библиотек и технологий.
  5. Комьюнити и поддержка. Существует огромная библиотека контейнеров с открытым исходным кодом. Можно скачать нужный образ для конкретной задачи или обратиться за помощью к большому комьюнити разработчиков, которые используют Docker.
  6. Непрерывность работы. С учетом инструментов управления трафиком можно построить процесс обновления приложения так, чтобы обновление одних контейнеров не влияло на работоспособность системы и оказание услуг пользователям.
  7. Упрощение администрирования. С помощью Docker легче перенести контейнер с одного хоста на другой, запустить сразу несколько образов, обновить группы контейнеров и откатиться к старой версии.
  8. Повышение уровня безопасности. Контейнеры в Docker частично изолированы друг от друга на уровне процессов и ОС, поэтому запуск большого количества контейнеров на одной машине не несет рисков.
  9. Экономическая эффективность. Контейнеры легковесны и производительны, а благодаря использованию Docker можно эффективнее управлять имеющимися ресурсами и сократить расходы компании.
  10. Современный подход. Отказ от монолитной архитектуры в пользу микросервисной позволяет более гибко развивать продукт, добавлять в него новые функции.

Основные компоненты Docker

Dockerfile. Текстовый файл с последовательно расположенными инструкциями для создания образа Docker. Файл создаётся по принципу «одна строка — одна команда».

Daemon. Фоновая служба на хосте, которая отвечает за создание, запуск и уничтожение контейнеров.

Image. Неизменяемый файл (образ), из которого можно неограниченное количество раз развернуть контейнер.

Client. Утилита командной строки в Docker для управления демоном. Любое взаимодействие с контейнером проходит через Daemon.

Container. Запущенное приложение, которое развернули из образа.

Registry. Служба в Docker, выполняющая функции репозитория (хранилища). Позволяет следить за версиями образов, создавать приватные репозитории.

Docker Hub. Популярный публичный репозиторий, используемый по умолчанию в Docker. Обеспечивает интеграцию с GitHub и BitBucket.

Docker Desktop. Приложение, позволяющее локально собирать, выполнять и тестировать контейнеры. Работает на Windows и macOS.

Docker volumes. Тома для постоянного хранения информации. По умолчанию в Docker папки хранилищ создаются на хост-машине, но предусмотрена и возможность подключения удаленных хранилищ. Использование томов позволяет лучшим образом настроить хранение данных.

Как устроен образ Docker

Базовый образ — главный элемент контейнеризации в Docker. В нем содержатся процессы и зависимости, необходимые для нормальной работы приложения. Разработчики предпочитают скачивать готовые образы из репозиториев, а не создавать их с нуля, так как уже есть огромное количество готовых компонент для самых разных задачи. Например, в Docker Hub уже загружено свыше 100 000 образов.

Образ — это неизменяемые слои, которые доступны только для чтения. А контейнер — это тот же самый образ, у которого «сверху» есть еще один слой для записи. Контейнер использует его, когда ему нужно сохранить информацию в процессе своей работы: логи, временные файлы и так далее. Если контейнер уничтожится, то этот слой и вся информация на нем тоже пропадут. А когда из этого же образа создастся новый контейнер, слой для записи у него будет новый и пустой.

На базовый образ в Docker один за другим накладываются доступные только для чтения слои, которые образуются после любых изменений в образе. Каждый новый слой — это актуальная версия образа. Получается, что финальный образ — это объединение всех слоев в один. Каждый слой образа сохраняется, чтобы при необходимости быстро откатываться назад. Такое решение экономит пространство диска и сокращает время сборки контейнера.

Если образ — это набор доступных только для чтения слоев, то контейнер представляет собой тот же образ, но с еще одним слоем сверху — с возможностью записи. Информация записывается в контейнер, а когда он уничтожается, верхний слой и содержащиеся в нем данные пропадают. В случае необходимости создается новый (чистый) контейнер из старого образа.

Когда к Docker-образу добавляется слой для записи, получается Docker-контейнер

В Dockerfile записываются команды и опции создания образа, а также некоторые настройки будущего контейнера, такие как порты, переменные окружения и другие опции.

Каждая команда записанная в dockerfile создаёт свой слой. Чем больше слоёв, тем дольше будет собираться образ и дольше загружаться контейнер. Финальный Docker-образ — это объединение всех слоев в один. Благодаря такому подходу можно переиспользовать уже готовые образа для создания новых образов.

В любом образе Docker хранится Docker manifest. Это JSON-файл, содержащий информацию об образе: ссылки на каждый существующий слой, данные об их размере, хеш, а также сведения о платформе, на которой он будет работать.

Теория создания образа Docker

Развертывать образ можно любое количество раз на любом хосте. Для создания образа используется один из двух способов: интерактивный или через Dockerfile.
Для работы с контейнерами Docker предоставляет всего несколько основных команд: docker run/stop/restart.

Интерактивный — простой способ, при котором разработчик сам изменяет среду окружения во время запуска контейнера. После запуска Docker в сессии терминала запустите оболочку контейнера (bash) командой docker run image_name: tag_name. Имя тега можно не указывать, тогда задействуется текущая версия образа.

Вариант с Dockerfile сложнее. Вы уже знаете, что каждому образу присваивается свой Dockerfile. После указания нужных команд в Dockerfile, исключите в .dockerignore все файлы, не используемые в сборке. Затем создайте образ командой docker image build, присвойте ему имя и тег.

Но как же быть, если мы хотим, скажем, запускать базы данных или иные приложения в контейнере, для которых важна целостность данных? Docker предлагает два решения:

  1. Монтирование папки с хоста к контейнеру. Такое решение отлично подходит для разработки и отладки приложения, когда вносимые изменения на хосте сразу отражаются в контейнере. Конечно, для продакшна такой подход не годится.
  2. Создание специальных томов для хранения данных — Docker volume. DV — это обычные каталоги хоста, которые могут быть смонтированы как отдельные файловые системы (bind mounting) внутри контейнера.

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

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

  • Cgroups (контрольные группы) — механизм управления ресурсами, используемыми контейнером (процессор, оперативная память и т.д.). С помощью cgroups Docker также реализует возможность остановки контейнеров — docker pause (freezing и unfreezing).
  • Namespaces (пространства имен) — механизм изоляции контейнеров, гарантирующий, что файловая система, имя хоста, пользователи, сетевая среда и процессы любого контейнера полностью отделены от остальной части системы.

Ещё одна технология, которую Docker использует для хранения слоев в контейнере — файловая система с каскадно-объединенным монтированием (Union File System – UnionFS). Как видите Docker умело использует уже хорошо работающие технологии, и в этом его сила.

Сами по себе контейнеры не эфемерны, более того Docker их не скрывает и вы можете совершенно спокойно заглянуть в них. Они располагаются здесь: /var/lib/docker/containers. Обращаться к контейнеру как к набору файлов бывает полезно, когда вам нужно прочитать логи контейнера.

Dockerfile — это конфигурационный файл с инструкциями по созданию Docker-образов. Почти каждая команда инструкции создаёт новый слой в образе. Это нужно для дальнейшего использования уже готовых слоев.

Например, мы изменили последнюю инструкцию в Dockerfile и собрали образ заново. Docker не будет заново всё пересобирать. Он возьмет все предшествующие слои и переиспользует их. Вот как образно выглядит соотношение инструкций в Dockerfile со слоями в Docker-образе:

Существуют определенные правила и логика заполнения Dockerfile. Разберем базовые инструкции на примере Dockerfile с иллюстрации выше.

1. FROM

Любой код или набор инструкций выполняется сверху вниз. Поэтому Dockerfile всегда начинается с открывающей инструкции FROM, которая говорит демону Docker, какой образ для основы нужно взять. Если образа локально нет — он будет скачан с Docker hub.

2. RUN

Далее идет инструкция RUN с определенной командой. В нашем случае мы использовали команду mkdir -p для создания папки /app. Инструкций RUN может быть неограниченное количество, но стоит помнить, что каждая инструкция создает свой слой, поэтому хорошей практикой является запись цепочки команд через &&: RUN comand_1 && comand_2 && comand_3.

3. WORKDIR

Есть инструкции логически связанные между собой. Инструкция WORKDIR устанавливает активный рабочий каталог. Все последующие команды, такие как COPY, RUN, CMD и некоторые другие будут выполнены из рабочего каталога, установленного через WORKDIR.

4. COPY

С инструкцией COPY всё просто. Первым аргументом указывается папка для копирования, а вторым аргументом — папка в контейнере куда будут помещены файлы из копируемой директории. В нашем случае, из текущего каталога (“.” — каталог, в котором находится пользователь, “..” — каталог выше относительно “.”.), в котором находится пользователь, был скопирован файл requirements.txt и помещен в папку /app в контейнере.

5. RUN

Инструкцию RUN мы рассмотрели ранее. Тут лишь хотим обратить ваше внимание на её поведение в сочетании с инструкцией WORKDIR. Ранее инструкция COPY перенесла файл requirements.txt в контейнер. Кстати, в качестве финального пути мы могли указать “.”, так как инструкция WORKDIR установила в качестве рабочей директории контейнера папку /app. И теперь команда RUN будет выполнена именно из директории /app.

6. CMD

Финальной инструкцией в любом Dockerfile является CMD или ENTRYPOINT. В отличие от других инструкций CMD может быть только одна и она может быть переопределена при старте контейнера командой docker run. Инструкция CMD наследует условия установленные инструкцией WORKDIR.

Не все инструкции указанные в Dockerfile непосредственно исполняются при сборке образа и запуске контейнера. Например, инструкция EXPOSE лишь говорит демону Docker, что мы намереваемся пробросить указанный нами порт наружу контейнера — EXPOSE 80. В этом примере мы хотим пробросить порт 80 изнутри контейнера наружу.

Однако после запуска контейнера «постучаться» на 80 порт к нему мы не сможем. Так как для подтверждения инструкции EXPOSE используется ключ -P команды docker run. Если требуется прокинуть порт и переназначить его снаружи — используется следующая команда: docker run -p 80:80 --name test_cont -d.

Сервисы для работы с контейнерами

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

Docker Compose

В составе Docker есть инструмент, который позволяет централизованно запускать большое количество сервисов: Docker Compose. Документирование и конфигурирование сервисов приложения осуществляется с помощью текстового YAML-файла. Команда docker‑compose up развертывает сервисы приложений и создает из образа новые контейнеры, а также сети, тома и все конфигурации, указанные в файле Docker Compose.

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

Yandex Container Registry

Поддерживает управление через интерфейс консоли, командной строки (CLI) и командной строки Docker на основе Docker Registry HTTP API V2, работу через API.

Доступны контейнеры с ОС Linux и Windows, которые можно запускать локально или на виртуальных машинах Yandex Compute Cloud.

Оркестрация

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

Docker Swarm

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

Kubernetes

Платформа для автоматизации работы с контейнерами на Ubuntu, CentOS и других ОС Linux. Позволяет централизованно группировать контейнеры, балансировать нагрузку, активировать сервисы из сотен приложений одновременно. Kubernetes предоставляет пользователям больше возможностей по сравнению со Swarm, но и настраивать его сложнее.»

OpenShift

OpenShift — это открытая и расширяемая платформа приложений-контейнеров, которая позволяет использовать Docker и Kubernetes на предприятии.

OpenShift включает Kubernetes для оркестрации контейнеров и управления ими. Здесь добавлены инструменты для разработчиков и операций, позволяющие:

  • быстро разрабатывать приложения;
  • легко развертывать и масштабировать решения;
  • обслуживать жизненный цикл команд и приложений в долгосрочной перспективе.

Существует несколько доступных версий OpenShift: платформа контейнеров OpenShift и OKD (прежнее название OpenShift Origin).

Как Docker помогает на практике?

Приведу несколько примеров использования Docker, которые хорошо иллюстрируют его преимущества.

Разработка приложений с зависимостями

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

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

Единый интерфейс управления исключает необходимость индивидуальных команд. Достаточно выучить команды Docker: как скачивать образы, запускать контейнеры, пробрасывать, останавливать и удалять порты. С Docker можно запустить сколько угодно одинаковых баз внутри одной операционки. Благодаря изоляции, если что-то пойдёт не так, ошибки не затронут операционную систему и ничего не сломают.

Автоматизация тестирования

Чтобы запустить автотесты, требуются определённые зависимости, например базы данных, брокеры сообщений и тому подобное. Их необходимо предварительно установить и сконфигурировать на сервере сборки. В этом месте иногда возникают проблемы: если при настройке упустить какую-то деталь, то можно испортить данные или что-то поломать. Гораздо безопаснее автоматически развернуть зависимости в виде контейнера прямо на сервере. Это позволяет быстро прогнать тесты, а после — бесследно удалить контейнеры.

Даже если тесты «сломают» какие-то данные, они удалятся вместе с контейнером. Кроме того, сам сервер с Docker, на котором запускаются автотесты, станет универсальным. Ведь благодаря контейнеризации на нём можно будет запускать что угодно. А значит, вы сэкономите на железе и настройке системы.

Публикация приложения

После тестирования проект упаковывают в образ и публикуют, передают клиентам или инфраструктурным инженерам.

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

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

Минусы Docker

Как известно, за удовольствие приходится платить. И Docker — не исключение.

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

Для больших приложений нужен оркестратор. Docker подходит для запуска нескольких контейнеров. В стандартной поставке Docker Compose есть механизм, который позволяет управлять их запуском с помощью конфигурационного файла YAML. Но этот механизм простой, он не потянет приложение, включающее 50–100 сервисов. У Docker не хватит механизмов управления и распределения ресурсов, резервирования и отказоустойчивости, чтобы реализовывать разные схемы обновления контейнеров.

В больших приложениях с микросервисной архитектурой используют оркестраторы Kubernetes или OpenShift. Единицей управления в Kubernetes является контейнер Docker, но на голом Docker прод практически никто не держит. Когда-то в России были такие компании — они рассказывали о своём травмирующем опыте на конференциях :)

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

Проблемы с установкой на Windows и macOS. Как я сказал ранее, Docker создавался под Linux. На других операционках он не поддерживает некоторые типы сетей. В большинстве случаев никто этого не заметит, но об этом ограничении нужно помнить. Также на некоторых устройствах возникает конфликт с Virtual Box при установке Docker на Windows.

Аналоги Docker

Docker стал стандартом де-факто в мире контейнеров. Часто, когда говорят про контейнеры, подразумевают именно Docker-контейнеры. Но это не единственная реализация технологии контейнеризации, есть и другие:

  1. PodManИмеет интерфейс командной строки, который очень похож на команды Docker. Основное отличие от докера заключается в том, что у Podman нет отдельного демона, это самостоятельная утилита. Podman используется как инструмент управления контейнерами по умолчанию в дистрибутиве Fedora Linux.
  2. LXCСистема виртуализации на уровне ОС, а не самостоятельная платформа, как Docker. Она создает отдельное виртуальное окружение с собственным пространством процессов и сетевым стеком, в котором все контейнеры используют один экземпляр ядра ОС. LXC часто рассматривается как среднее между chroot и полноценной виртуальной машиной.
  3. rktДвижок, который изначально был ориентирован на современные облачные приложения. В 2019 году разработка прекратилась, и движок переведен в архив. Возможно, еще можно встретить проекты, где он используется. Но в новых разработках rkt уже не стоит выбирать.

Docker подходит для облаков

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

Как изучать Docker

Я рекомендую изучать Docker по книгам, сайтам и закреплять прочитанное на практике.

Книги. Есть две хорошие книги — Using Docker и Docker in Action. Правда, они немного устарели (опубликованы в 2018–2019 годах), поэтому там может быть неактуальная информация. Надеюсь, скоро будет переиздание.

Сайт docker.com — основной сайт Docker. На нём есть справочники и референсы по Docker, Docker-файлам, образам и Docker Compose. Читаете книгу, проверяете на сайте актуальность команд и изучаете примеры.

Упражнения.

  • Установите Docker на рабочий компьютер. Возьмите готовый Docker image с Docker Hub с базой данных и запустите на его основе контейнер. Это можно сделать по инструкции, которую производитель image выкладывает на Docker Hub. Затем подключитесь к запущенной БД каким-нибудь клиентом и убедитесь, что всё работает.
  • Напишите простенький сервис REST API и Docker-файл для упаковки сервиса в образ, подглядывая в референсы или книгу. Ваша задача — разобраться в теории, получить Docker image и проставить теги.
  • Из полученного ранее образа создайте и запустите контейнер. Вам придётся разобраться с параметрами команды Docker run, настройками портов, передачей переменных окружению, монтированием и основными параметрами. Также стоит научиться подключаться к контейнеру, выполнять bash-команды и смотреть логи приложения.
  • Усложните тестовый сервис, научив его работать с базой данных. Затем разверните контейнеры с сервисом и базой данных и соедините их внутренней сетью. Простое и в то же время очень полезное упражнение, на котором очень часто возникают затруднения на собеседованиях.
  • Переходим к Docker Compose. Посмотрите, как написать YAML и создать группу контейнеров, как соединять их в сеть и работать с маунтами.
  • Опубликуйте свой Docker image в Docker Hub. На одном аккаунте можно бесплатно публиковать только один образ, но есть GitLab, где нет таких ограничений. Правда, он устроен немного сложнее, новичок может запутаться. Ещё в том же GitLab можно создать приватный registry-режим и публиковать проекты без ограничений.