Этот туториал является 2-ой частью из 5-ти в серии статей Экосистема Docker.
На пути продвижения Вашего приложения через цикл разработки и, в конечном итоге, в эксплуатацию зачастую встречается множество препятствий. Помимо работы по подготовке приложения к работе в различных условиях, Вы также можете столкнуться с проблемами отслеживания зависимостей, масштабирования приложения и обновлений отдельных компонентов, не затрагивающих непосредственно само приложение.
Docker-контейнеризация и сервис-ориентированное проектирование пытаются решить многие из этих проблем. Приложения могут быть разбиты на управляемые функциональные компоненты, индивидуально упакованные вместе со всеми своими зависимостями, а затем легко развернуты на нестандартной архитектуре. Это также упрощает масштабирование и обновление компонентов.
В данной статье мы обсудим преимущества контейнеризации и то, как Docker помогает решить многие из упомянутых выше проблем. Docker - ключевой компонент для распределенного развёртывания контейнеров, предоставляющий возможность легкого масштабирования и управления.
Контейнеризация и изолирование компонентов не новые концепции в мире вычислений. Некоторые Unix-подобные операционные системы используют “зрелые” контейнерные технологии уже более 10 лет.
Система LXC (Linux Containers) - основа последующих технологий контейнеризации - была добавлена в ядро Linux в 2008 году. LXC использует комбинацию таких функция ядра, как cgroups (позволяет изолировать и отслеживать использование ресурсов) и пространства имен (позволяют разделять группы так, чтобы они не могли “видеть” друг друга), для реализации легковесной изоляции процессов.
Docker, появившийся несколько позже, позиционировался, как инструмент для упрощения работы по созданию и управлению контейнерами. Изначально Docker использовал LXC в качестве драйвера исполнения по умолчанию (с тех пор для этих целей была разработана библиотека под названием libcontainer
). Docker, не привнося большого количества новых идей, сделал контейнеры доступными для обычного разработчика и системного администратора путем упрощения процесса и стандартизации интерфейса. Это стимулировало возрождение интереса к контейнеризации среди разработчиков в Linux-мире.
Несмотря на то, что некоторые из тем, которые мы обсуждаем в этой статье, являются более общими, мы будем фокусироваться в основном на Docker-контейнеризации, ввиду его огромной популярности и стандарта де-факто.
Контейнеры несут в себе много привлекательных преимуществ как для разработчиков, так и для системных администраторов.
Некоторые из наиболее заманчивых преимуществ перечислены ниже.
Контейнеры задуманы быть полностью стандартизованными. Это означает, что контейнер соединяется с хостом или чем-либо внешним по отношению к нему при помощи определенных интерфейсов. Контейнеризованное приложение не должно полагаться или каким-то образом зависеть от ресурсов или архитектуры хоста, на котором оно работает. Это упрощает предположения об среде выполнения приложения в процессе разработки. Аналогично, со точки зрения хоста, каждый контейнер представляет собой “черный ящик”. Хосту нет дела то того, что за приложение внутри.
Одним из преимуществ абстрагирования между операционной системой хоста и контейнерами является то, что при правильном проектировании приложения, масштабирование может быть простым и прямолинейным. Сервис-ориентированная архитектура (будет рассмотрена далее) в комбинации с контейнеризованными приложениями обеспечивает основу для лёгкого масштабирования.
Разработчик может запустить несколько контейнеров на своей рабочей машине, при этом та же система может быть горизонтально масштабирована, например, на тестовой площадке. Когда контейнеры запускаются в эксплуатацию (продакшн), они снова могут быть масштабированы.
Контейнеры позволяют разработчику связать приложение или компонент приложения со всеми его зависимостями и дальше работать с ними как с единым целым. Хосту не надо беспокоиться о зависимостях, необходимых для запуска конкретного приложения. Если хост может запустить Docker, он может запустить любой Docker-контейнер.
Это делает лёгким управление зависимостями и также упрощает управление версиями приложения. Хост-системы больше не должны отвечать за управление зависимостями приложения, потому что, за исключением случаев зависимости одних контейнеров от других контейнеров, все зависимости должны содержаться в самом контейнере.
Не смотря на то, что контейнеры не предоставляют такого же уровня изоляции и управления ресурсами, как технологии виртуализации, они обладают чрезвычайно лёгкой средой исполнения. Контейнеры изолированы на уровне процессов, работая при этом поверх одного и того же ядра хоста. Это значит, что контейнер не включает в себя полную операционную систему, что приводит к практически мгновенному его запуску. Разработчики могут легко запустить сотни контейнеров со своей рабочей машины без каких-либо проблем.
Контейнеры легки еще и в том смысле, что они сохраняются “послойно”. Если несколько контейнеров основаны на одном и том же слое, они могут совместно использовать этот базовый слой без дублирования, что приводит к минимальной загрузке дискового пространства в последующих образах.
Docker-файлы позволяют пользователям задать конкретные действия, необходимые для создания нового образа контейнера. Это позволяет Вам задавать настройки среды исполнения так, как будто бы это код, при желании сохраняя эти настройки в системе контроля версий. Одинаковый Docker-файл, собранный в одном и том же окружении, всегда создаст идентичный образ контейнера.
Когда есть возможность создать образы контейнеров в интерактивном режиме, обычно лучше записать шаги конфигурации в Docker-файл. Docker-файлы это простые файлы сборки (build-файлы), которые описывают процесс создания образа контейнера с известной начальной точки.
Docker-файлы невероятно полезны и ими довольно легко начать пользоваться. Вот лишь некоторые из преимуществ, которые они предоставляют:
Docker-файлы являются отличным инструментом автоматизации построения образов контейнеров для создания повторяемого процесса их построения.
При проектировании приложений, которые будут разворачиваться в контейнерах, один из первых возникающих вопросов это архитектура приложения. Обычно, контейнеризованные приложения лучше всего работают при сервис-ориентированной архитектуре.
Сервис-ориентированные приложения разбивают функциональность системы на отдельные компоненты, которые взаимодействуют между собой через четко определенные интерфейсы. Сама контейнерная технология поощряет такой тип проектирования, потому что он позволяет независимо масштабировать или обновлять каждый компонент.
Приложения, реализующие этот подход к проектированию, должны иметь следующие характеристики:
Эти стратегии позволяют заменять или изменять каждый компонент независимо (до тех пор, пока поддерживается API). Они также фокусируются на горизонтальной масштабируемости, ввиду того, что каждый компонент может быть масштабирован в соответствии с выявленным узким местом.
Вместо жёсткого задания конкретных значений, для каждого компонента обычно можно определить необходимые значения для использования по умолчанию. Компонент может использовать эти значения в качестве резервных, но должен отдавать предпочтение значениям, полученным из окружения. Обычно это достигается при помощи инструментов обнаружения сервисов, которые компонент может опрашивать в процессе запуска.
Вынос конфигурации из самого контейнера и помещение её в окружение позволяет легко менять поведение приложения без изменения образа контейнера. Это также позволяет одной настройке влиять на несколько экземпляров компонента. В целом, сервис-ориентированное проектирование хорошо сочетается со стратегиями внешнего конфигурирования, потому что и то, и другое способствует более гибкому развёртыванию и более прямолинейному масштабированию.
Когда Ваше приложение разделено на функциональные компоненты и сконфигурировано правильно отвечать другим контейнерам в своём окружении, следующий логичный шаг - сделать Ваши образы контейнеров доступными через Docker-реестр. Загрузка образов контейнеров в реестр позволяет Docker-хостам загружать и разворачивать экземпляры (инстансы) контейнера, просто зная имя образа.
Для этой цели существуют множество Docker-реестров. Некоторые из них - публичные, в которых каждый может видеть и использовать сохраненные в него образы, другие реестры - приватные. К образам можно добавлять теги, чтобы их было проще найти для загрузки или обновления.
Docker обеспечивает фундаментальную основу, необходимую для распределённого развёртывания контейнеров. При помощи упаковки компонентов приложения в отдельные контейнеры, горизонтальное масштабирование становится просто задачей развертывания или остановки нескольких экземпляров каждого компонента. Docker предоставляет необходимые инструменты не только для построения контейнеров, но и для управления и разделения их с другими пользователями или хостами.
Хотя контейнеризованные приложения и обеспечивают необходимую изоляцию процессов и упаковку приложений для помощи в их развертывании, существует множество других компонентов, необходимых для надлежащего управления и масштабирования контейнеров на распределенном кластере хостов. В следующей статье мы обсудим, что привносят в развёртывание кластеризованных контейнеров поиск служб и глобально распределённые конфигурационные хранилища.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Экосистема Docker
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!