Рецензия: Docker на практике. Второе издание

2023.09.06
На момент написания книги Docker фактически стал стандартом в IT мире. Авторы рассматривают различные аспекты использования Docker начиная от запуска контейнеров и заканчивая безопасностью.

Docker на практике

Я взялся за прочтение книги имея некоторый опыт работы Docker, Docker Compose и даже с Docker Swarm. Читая книгу много было знакомо, но вторая половина книги была кратким полетом над множеством возможностей, которые я не использовал.

Зачем Docker?

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

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

Вспомним как настраивать web-сервер для php или как устанвлить redmine ... К счастью, уже есть готовые образы redmine, а lamp можно самому поднять в docker compose используя образы apache и php.

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

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

Как изменилась жизнь с Docker

Авторы утверждают что:

Основная функция Docker – создавать, отправлять и запускать программное обеспечение в любом месте, где есть Docker.

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

Но откуда такая простота и легкость использования? Факторов несколько, среди них принцип: 1 контейнер - 1 процесс:

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

Конечно, говоря о какой-либо новой технологии, а Docker появился относительно недавно (2013 год), следует рассматривать инструмент в контексте решения существующих проблем. Один из таких аспектов:

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

Эта четкая линия обеспечивается за счет принципа единой ответсвенности.

А что если взглянуть на Docker как на инструмент упаковки инфраструктуры?

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

Первая часть книги посвящена знакомству: что такое образы, контейнеры, реестры, как писать Dockerfile собирать образы и запускать контейнеры, которые могут друг с другом общаться.

Виртуальные машины VS Docker контейнеры

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

Но я заметил общее между противниками контейнеризации, они задают вопрос: зачем виртуализация в виртуализации?

А у новичнов возникает более корректный вопрос, который не смердит профанацией: в чем разница между контейнерами Docker и виртуальными машинами?

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

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

В конечно итоге авторы резюмируют отличие контейнеризации от виртуализации в трех пунктах:

ENTRYPOINT & CMD

Когда я только начинал осваивать Docker, для меня как и для других новичков было не понятно различие ENTRYPOINT и CMD ведь обе инструкции по отдельности принимают команду для выполнения при запуске контейнера, но это не так. Авторы дают этому четкое разграничение:

Разница между ENTRYPOINT и CMD часто сбивает с толку. Ключевым моментом для понимания является то, что точка входа (ENTRYPOINT) всегда будет запускаться при запуске образа, даже если для вызова docker run указана команда. Если вы попытаетесь ввести команду (CMD), она добавит это как аргумент к точке входа (ENTRYPOINT), заменив значение по умолчанию, определенное в инструкции CMD. Вы можете переопределить точку входа, только если явно передаете флаг --entrypoint.

А по ходу изучения примеров это различие становится явным, особенно на примере "МЕТОД 114 Извлечение файла из образа", когда ENTRYPOINT и CMD используются вместе.

Инструменты

В книге кратко но по сути описаны методы и инструменты оркестрации, начиная с консервативных в виде systemd, проходя через Helios, Mesos, Swarm, Kubernetes (и прочее) и заканчивая облачными решениями типа AWS.

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

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

Несмотря на наличие перечисления облачных платформ, явно присутствует здравый смысл:

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

Но есть другой вариант (хотя что может быть противоположностью здравого смысла?):

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

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

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

А для конфигурации среды выполнения есть примеры на etcd, но с аналогичным успехом можно встроить Consul.

Кончено не обошли стороной вопрос DevOps философии про CI/CD конвейеры, где для CI есть примеры с использование Jenkins, а для CD примеры с etcd и confd.

Безопасность

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

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

Но мы можем ограничить пользователя root в контейнерах при помощи мандатов, эта тема раскрывается достаточно широко чтобы новичку понять основы (даже есть таблица мандатов):

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

Docker по умолчанию отключил некоторые мандаты. Это означает, что даже если у вас есть root в контейнере, некоторые вещи вы не сможете сделать.

Один из крайних подходов – удалить из контейнера все мандаты, которые по умолчанию включены в Docker, и посмотреть, что перестанет работать.

Немного оффтопа: на тему безопасности Docker было интересное выступление Сергея Задорожного на Dackend Day в городе Иннополис.

Ограничения

Мы дошли до финальной части книги. На пути нам довелось изучить различное использование Docker в сочетании с привычными нам инструментами, благодаря абстракциям Docker. Но абстракции не даются просто так, они чего-то стоят. Авторы книги "Docker на практике" не обходят этот вопрос стороной.

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

Особенно интересует сеть, так как в большинстве случаев наши приложения работают с сетью:

В то время как нативная сеть должна проходить только через стек TCP/IP хоста к сетевой плате (NIC), Docker должен дополнительно поддерживать виртуальную пару Ethernet (vethпара – виртуальное представление физического соединения через кабель Ethernet), сетевой мост между этой vethпарой и сетью хоста и уровня преобразования сетевых адресов.

Native Network VS Docker NAT

Однако, ограничения налагаемые абстракциями Docker может обойти просто отключив их. Самый яркий пример это --net=host когда мы отключаем внутренюю сеть контейнера и внутри использую сеть хоста.

Я уже рассматривал в своем ТГ канале 2 случая когда новые образы не заводились с первого раза на старых система со старой версией Docker, но в конечном итоге их удавалось запустить, а причина проста:

Docker рассматривает API ядра Linux как его хост (среду, в которой он может работать). Когда впервые узнают, как работает Docker, многие спрашивают, как он обрабатывает изменения в API Linux. Насколько мы знаем, он этого еще не делает. К счастью, API интерфейс Linux обратно совместим, но нетрудно представить себе сценарий в будущем, когда создается новый API вызов интерфейса Linux и используется Docker'изированным приложением, а затем это приложение развертывается в ядре, достаточно новом для запуска Docker, но достаточно старом, чтобы не поддерживать этот вызов.

И это еще одна причина простоты и легкости использования Docker.

Понимая возможности и иограничения, мы можем производить тестирование и отладку контейнеров. В книге есть примеры тестирования сети при помощи comcast и blockade, а для отладки контенеров есть примеры с nsenter и tcpflow.

Резюме

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

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

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

В телеграм канале DevOps от первого лица можно оставить комментарий или почитать интересные истории из практики DevOps