какая ас включает в себя репозиторий образов контейнеров
Изучаем Docker, часть 1: основы
Технологии контейнеризации приложений нашли широкое применение в сферах разработки ПО и анализа данных. Эти технологии помогают сделать приложения более безопасными, облегчают их развёртывание и улучшают возможности по их масштабированию. Рост и развитие технологий контейнеризации можно считать одним из важнейших трендов современности.
Docker — это платформа, которая предназначена для разработки, развёртывания и запуска приложений в контейнерах. Слово «Docker» в последнее время стало чем-то вроде синонима слова «контейнеризация». И если вы ещё не пользуетесь Docker, но при этом работаете или собираетесь работать в сферах разработки приложений или анализа данных, то Docker — это то, с чем вы непременно встретитесь в будущем.
Если вы пока не знаете о том, что такое Docker, сейчас у вас есть шанс сделать первый шаг к пониманию этой платформы. А именно, освоив этот материал, вы разберётесь с основами Docker и попутно приготовите пиццу.
Метафоры и Docker
Мы постоянно сталкиваемся с метафорами. Если заглянуть в словарь Ожегова, то окажется, что метафора — это «скрытое образное сравнение, уподобление одного предмета, явления другому». Метафоры помогают нам ухватывать суть новых для нас явлений. Например, виртуальные контейнеры можно сравнить с обычными пластиковыми контейнерами. Такое сравнение, через сопоставление уже известных нам свойств обычных контейнеров со свойствами виртуальных контейнеров, поможет сначала с ними познакомиться, а потом и понять их сущность.
Как вы понимаете, мы собираемся начать разговор о Docker с понятия «контейнер».
Контейнер
Как и обычный пластиковый контейнер, контейнер Docker обладает следующими характеристиками:
Живые организмы
Ещё один подход к размышлениям о контейнерах Docker заключается в сравнении их с экземплярами живых организмов. «Экземпляр» — это нечто, существующее в некоей форме. Это не просто код. Это код, который стал причиной существования чего-то большего, чем он сам, чего-то, образно говоря, живого. Как и другие живые организмы, экземпляры контейнеров появляются на свет, живут и умирают.
Монстр, вызванный к жизни
Контейнеры Docker — это вызванные к жизни образы Docker.
Программное обеспечение
Контейнеры Docker можно сравнивать не только с обычными контейнерами или с живыми организмами. Их можно сравнить и с программами. В конце концов, контейнеры — это программы. И, на фундаментальном уровне, контейнер представляет собой набор инструкций, который выполняется на некоем процессоре, обрабатывая какие-то данные.
Контейнер — это программа
Во время выполнения контейнера Docker внутри него обычно выполняется какая-то программа. Она выполняет в контейнере некие действия, то есть — делает что-то полезное.
Например, код, который работает в контейнере Docker, возможно, отправил на ваш компьютер тот текст, который вы сейчас читаете. Вполне возможно и то, что именно код, выполняющийся в контейнере Docker, принимает голосовые команды, которые вы даёте Amazon Alexa, и преобразует их в инструкции для ещё каких-нибудь программ, работающих в других контейнерах.
Благодаря использованию Docker можно, на одном и том же компьютере, одновременно запускать множество контейнеров. И, как и любые другие программы, контейнеры Docker можно запускать, останавливать, удалять. Можно исследовать их содержимое и создавать их.
Концепции Docker
▍Виртуальные машины
Предшественниками контейнеров Docker были виртуальные машины. Виртуальная машина, как и контейнер, изолирует от внешней среды приложение и его зависимости. Однако контейнеры Docker обладают преимуществами перед виртуальными машинами. Так, они потребляют меньше ресурсов, их очень легко переносить, они быстрее запускаются и приходят в работоспособное состояние. В этом материале можно найти подробное сравнение контейнеров и виртуальных машин.
▍Образ контейнера Docker
Выше мы уже говорили об «образах». Что это такое? Хороший вопрос. То, что в терминологии Docker называется «образом», или, по-английски, «image», это совсем не то же самое, что, например, фотография (это — одно из значений слова «image»).
Образы Docker — это не фотографии
Образы контейнеров Docker можно сравнить с чертежами, с формочками для печенья, или с пресс-формами для изготовления пластиковых изделий. Образы — это неизменные шаблоны, которые используются для создания одинаковых контейнеров.
Образы контейнеров Docker похожи на формочки для печенья
В образе контейнера Docker содержится образ базовой операционной системы, код приложения, библиотеки, от которого оно зависит. Всё это скомпоновано в виде единой сущности, на основе которой можно создать контейнер.
▍Файл Dockerfile
Файл Dockerfile содержит набор инструкций, следуя которым Docker будет собирать образ контейнера. Этот файл содержит описание базового образа, который будет представлять собой исходный слой образа. Среди популярных официальных базовых образов можно отметить python, ubuntu, alpine.
И, наконец, в образе может содержаться, поверх всех остальных, ещё один тонкий слой, данные, хранящиеся в котором, поддаются изменению. Это — небольшой по объёму слой, содержащий программу, которую планируется запускать в контейнере.
▍Контейнер Docker
▍Репозиторий контейнеров
Если вы хотите дать возможность другим людям создавать контейнеры на основе вашего образа, вы можете отправить этот образ в облачное хранилище. Самым крупным подобным хранилищем является репозиторий Docker Hub. Он используется при работе с Docker по умолчанию.
Мы уже довольно много всего обсудили. Пришло время собрать всё это вместе и сравнить работу с контейнерами Docker с приготовлением пиццы.
Готовим с Docker
Готовая пицца — это контейнер
Духовка — это платформа Docker
Духовка, в которой готовится пицца, напоминает платформу Docker. Духовку устанавливают на кухне, с её помощью можно готовить еду. Точно так же Docker устанавливают на компьютере для того, чтобы «готовить» контейнеры.
Духовку, если она электрическая, включают, поворачивая ручку регулятора температуры. Команда docker run image_name — это нечто вроде такого регулятора температуры, «поворот» которого приводит к тому, что система создаёт и запускает контейнер.
Готовая пицца — это и есть контейнер Docker.
А есть пиццу — значит пользоваться приложением, запущенным в контейнере.
Как и приготовление пиццы, подготовка к работе контейнеров Docker занимает некоторое время, но в финале и в том и в другом случаях получается что-то вкусное.
Итоги
Здесь мы, на концептуальном уровне, рассмотрели основы Docker. Надеемся, приведённые здесь сравнения помогли вам разобраться в том, что такое Docker, и ощутить ценность метафор в деле освоения новых технологий.
Уважаемые читатели! Эта публикация представляет собой перевод первой статьи из серии учебных материалов по Docker. По словам автора, всего планируется выпустить 5 таких материалов. Уже готовы вторая, третья и четвёртая части. Подскажите нам, стоит ли переводить следующие статьи этой серии?
Различия между Docker, containerd, CRI-O и runc
Появление Docker привело к взрывному росту популярности контейнеров, но с тех пор появились и другие инструменты. К сожалению, разобраться в них может быть совсем непросто. Но мы попробуем! И если вы считаете себя единственным, кто всего этого пока не понимает, не волнуйтесь. Это не так!
Что такое Docker?
Существует разница между компанией Docker, контейнерами Docker, образами Docker и инструментами Docker, к которым мы все привыкли. Важно понимать, что Docker — лишь один из инструментов для работы с контейнерами; существуют и другие инструменты, причем некоторые из них поддерживает сама компания Docker.
Как видите, вы не единственный, кто сбит с толку. Давайте разберёмся, чем отличаются Docker, containerd и CRI-O. Это особенно важно, если вы работаете с Kubernetes.
Обзор экосистемы контейнеров
Экосистема контейнеров состоит из множества технологий, специальной терминологии и компаний, конкурирующих друг с другом. К счастью, компании иногда заключают хрупкое перемирие, чтобы согласовать некоторые стандарты. Эти стандарты помогают добиться совместимости между различными инструментами и избежать зависимости от одной компании или проекта. Основные стандарты, о которых необходимо знать:
Container Runtime Interface (CRI) определяет API между Kubernetes и Container Runtime (средой выполнения контейнеров).
Open Container Initiative (OCI) определяет стандарт образов и контейнеров.
На этой иллюстрации показано, как Docker, Kubernetes, OCI, CRI, containerd и runc вписываются в эту экосистему:
Docker
Мы начнем с Docker, потому что это самый популярный инструмент для работы с контейнерами в настоящий момент. Для многих само название «Docker» является синонимом слова «контейнер».
Компания Docker создала очень удобный инструмент для работы с контейнерами. Docker можно установить на ноутбук (Docker Desktop) или сервер (Docker Engine). Он содержит набор инструментов, упрощающих труд разработчиков и DevOps—инженеров. С помощью Docker CLI можно создавать образы контейнеров, работать с репозиториями, создавать, запускать и управлять контейнерами.
Docker состоит из трех проектов:
containerd: Linux Daemon, который управляет контейнерами и запускает их. Он загружает образы из репозитория, управляет хранилищем и сетью, а также контролирует работу контейнеров.
runc: низкоуровневая среда выполнения контейнеров, которая создает и запускает контейнеры.
Dockershim: Docker в Kubernetes
Важно помнить, что Kubernetes поддерживает только Container Runtime, которые работают с Container Runtime Interface (CRI), но Docker не поддерживает этот стандарт напрямую, поэтому Kubernetes включает компонент под названием dockershim, который необходим для работы с Docker.
Компонент, который функционирует как мост между различными API, обеспечивая совместимость.
В дальнейшем Kubernetes откажется от поддержки dockershim и, соответственно, Docker и будет работать только с Container Runtime, поддерживающими Container Runtime Interface (CRI) — containerd или CRI-O.
Но это не означает, что Kubernetes не сможет запускать контейнеры из Docker—образов. И containerd, и CRI-O могут запускать образы в формате Docker (фактически в формате OCI), они просто делают это без использования команды docker и Docker Daemon.
Docker—образы
Container Runtime Interface (CRI)
CRI — это API, который Kubernetes использует для управления различными Container Runtime, создающими и управляющими контейнерами. CRI упрощает для Kubernetes использование различных Container Runtime. Вместо того, чтобы включать в Kubernetes поддержку каждой из них, используется стандарт CRI. При этом задача управления контейнерами полностью ложится на Container Runtime.
Поэтому, если вы можете использовать containerd для запуска контейнеров, вы также можете использовать CRI-O, потому что они поддерживают стандарт CRI. При этом, если вы конечный пользователь, то вам не важно, какая Container Runtime используется.
Помните, что Red Hat (проект OpenShift) использует CRI-O и отвечает за его поддержку (безопасность, исправления ошибок и т. д.). В то время как Docker поддерживает containerd.
Какая Container Runtime используется в Kubernetes
containerd
сontainerd — это Container Runtime, которая раньше была частью Docker. Реализует спецификацию CRI. Умеет скачивать образы из репозитория и управляет ими, а затем передает их Container Runtime нижнего уровня (о ней речь пойдет дальше), которая фактически создает и запускает процессы контейнера.
сontainerd был выделен из проекта Docker, чтобы сделать Docker модульным. Таким образом, Docker сам использует containerd. Когда вы устанавливаете Docker, он также устанавливает containerd. Кроме того, сontainerd использует собственный плагин для поддержки CRI в Kubernetes.
CRI-O — это еще одна Container Runtime, реализующая Container Runtime Interface (CRI). Она была специально создана с нуля при поддержке Red Hat, IBM, Intel и SUSE как Container Runtime для Kubernetes. Это альтернатива containerd, которая также позволяет загружать образы контейнеров из репозиториев, управлять ими и запускать Container Runtime нижнего уровня для запуска процессов контейнера.
Open Container Initiative (OCI)
OCI — это группа компаний, которые поддерживают спецификацию формата образа контейнера и метода запуска контейнеров. Идея OCI заключается в том, что вы можете выбирать между различными Container Runtime, которые соответствуют этой спецификации. При этом каждая из них может иметь разные реализации нижнего уровня. Например, у вас, может быть, одна OCI-совместимая Container Runtime для ваших хостов Linux и одна для ваших хостов Windows. В этом заключается преимущество стандартизации.
runc — это еще одна среда выполнения контейнера, совместимая с OCI, которая запускает процессы контейнеров. runc называют эталонной реализацией OCI.
Что такое эталонная реализация?
Эталонная реализация — это программное обеспечение, в котором реализованы все требования спецификации или стандарта. В случае с OCI runc предоставляет все функции, ожидаемые от OCI-совместимой среды выполнения.
Вот несколько альтернатив runc:
crun: среда выполнения контейнеров, написанная на C (в отличие от runc, которая написана на Go).
kata-runtime: из проекта Katacontainers, который реализует спецификацию OCI как отдельные небольшие виртуальные машины (аппаратная виртуализация).
Есть ли аналоги runc для Windows?
runc — это инструмент для запуска контейнеров в Linux. В Windows всё немного иначе. Эквивалент runc — это служба Microsoft Host Compute Service (HCS). Она содержит инструмент под названием runhcs, который является форком runc и также реализует спецификацию Open Container Initiative.
Подведем итоги
Docker — это лишь часть всей экосистемы контейнеров. Существуют открытые стандарты: CRI и OCI, и несколько Container Runtime с поддержкой CRI: containerd, runc, CRI-O и, конечно, сам Docker. Возможно, скоро мы увидим множество новых реализаций Container Runtime с поддержкой стандартов CRI и OCI.
Сравнение современных построителей образов контейнеров: Jib, Buildpacks и Docker
В этой статье будут рассмотрены и сравнены различные методы контейнеризации Java-приложений.
Вступление
Docker приобрел огромную популярность с момента своего дебюта в 2013 году. Многие предприятия полагаются на Docker для контейнеризации своих приложений. Многие вещи благоприятствуют популярности Docker, например, то, что он обеспечивает изоляцию, согласованную среду и идеально подходят для сценариев использования микросервисов, что делает его незаменимым для создания контейнеров. Однако в мире технологий нет ничего постоянного, и всегда есть альтернатива. Часто возникает необходимость исправить недостатки инструмента. Так в чем же недостатки Docker? Я бы, во-первых, включил необходимость root-доступа и, во-вторых, зависимость от процесса-демона.
В этом сообщении мы обсудим с нуля Docker и его альтернативы, достойные рассмотрения для контейнеризации ваших Java-приложений. Эти инструменты позволят вам получить контейнерное приложение с минимальными установками и настройками. Вероятно, вам даже не потребуется устанавливать Docker или работать с Dockerfile. К концу этой статьи вы сможете решить, какой построитель образов контейнера является самым быстрым, потребляет наименьшее количество ресурсов, проще в настройке и лучше всего подходит для вашего сценария использования.
Сравниваемые инструменты
В этой статье мы рассмотрим основные концепции и приведем краткое пошаговое руководство для следующих инструментов построения образов контейнеров:
Структура сравнения
Мы будем использовать следующие критерии и характеристики для анализа инструментов построения образов контейнеров.
Потребление ресурсов (память, дисковое пространство и т. д.)
Время, затраченное на создание образа (первая сборка или последующая сборка)
Оптимизация слоев образов
Пререквизиты
Если вы хотите продолжить, убедитесь, что у вас есть следующее:
Rancher для разработчиков, если вы планируете развертывать и запускать созданные образы
IDE по вашему выбору
Проект Spring Boot с версией 2.3 или выше
Анатомия приложения Spring Boot
Альтернативный вариант: Jib
Главное в Jib заключается в том, что вам не нужно ничего знать об установке Docker или поддержке Dockerfile. Jib не имеет демона. Более того, как разработчик, вы заботитесь только об артефакте (jar, war и т. д.), Который вы создадите, и вам не нужно иметь дело с какой-либо ерундой Docker (сборка / push и т. д.). Разработчику Java просто нужно добавить плагин к инструменту сборки по своему выбору (Maven / Gradle), и все. Вам не нужно проходить множество руководств, чтобы изучить такие технологии, как Docker, для контейнеризации вашего Java-приложения.
Создание образа с помощью Jib
Перед созданием образа вам необходимо добавить поддержку Jib в ваше Spring Boot приложение. Мы можем включить эту поддержку, просто добавив плагин Maven или Gradle в ваш файл pom.xml или build.gradle. Начать работу с Jib несложно.
Для Maven Spring Boot Project добавьте в файл pom.xml следующее:
Для Gradle Spring Boot Project добавьте в файл build.gradle следующее:
Кроме того, слои, создаваемые Jib, строятся поверх базового образа без дистрибутива. По умолчанию Jib использует образ Java 8 без дистрибутива, но вы можете выбрать образ по своему усмотрению. В этой демонстрации мы сосредоточимся на контейнеризации приложения с помощью плагина Maven Jib. Чтобы отправить образ в выбранный вами реестр контейнеров, вам необходимо добавить учетные данные реестра в maven settings.xml. Вы также должны просмотреть этот пост о том, как выполнить настройку для разных реестров контейнеров. Например, можно использовать следующую конфигурацию для отправки образа в реестр контейнеров DockerHub.
Мы можем начать создание образа с помощью следующей команды:
Он скомпилирует, построит и затем отправит образ вашего приложения в настроенный реестр контейнеров. Ниже приводится результат.
Ниже приводится результат:
Ниже показано использование памяти docker stats после запуска нашего приложения Spring Boot Hello-World в качестве контейнера Docker.
Вторая альтернатива: Buildpacks
Cloud Native Buildpacks преобразует исходный код вашего приложения в образы, которые можно запускать в любом облаке.
Создание образа с помощью Buildpacks
Начиная с версии 2.3, Spring Boot включает прямую поддержку Buildpack как для Maven, так и для Gradle. Одна команда может дать вам разумный образ вашего локально запущенного демона Docker. Buildpack требует, чтобы демон docker был запущен и работал. Если у вас не запущен демон docker, вы получите следующую ошибку при выполнении команды Maven.
Для Maven Spring Boot Project запустите сборку с помощью следующей команды:
Для Gradle Spring Boot проекта запустите сборку с помощью следующей команды:
Поведение сборки пакетов по умолчанию с помощью Spring Boot заключается в том, чтобы сохранить образ локально для демона Docker. Однако вы также можете отправить свои образы в удаленный реестр контейнеров. Чтобы это сработало, нам необходимо внести следующие изменения в файл Maven pom.xml.
Сначала мы попытаемся создать и опубликовать образ для локального демона Docker. Начнем сборку с команды mvn spring-boot:build-image Maven Build. Ниже приводится результат.
Теперь мы создадим и разместим образ в удаленном реестре контейнеров.
Ниже показано использование памяти docker stats после запуска нашего приложения Spring Boot Hello World в качестве контейнера Docker.
Альтернатива третья: Docker
Наивный способ создания образа с помощью Docker
Вот Dockerfile для нашего приложения Spring Boot Hello-World.
Инструкция FROM указывает базовый образ для нашего приложения
Инструкция COPY, как следует из названия, скопирует локальный jar-файл, созданный Maven, в наш образ.
Инструкция точки входа действует как исполняемый файл для нашего контейнера при запуске
Профессиональный способ создания образа с помощью Docker Multistage Build
В предыдущем разделе наш процесс был немного утомительным, а размер выходного образа был большим. Мы можем улучшить этот процесс и создавать тонкие образы с помощью многоступенчатых сборок Docker. Еще одна проблема с предыдущим методом заключалась в том, что нужно сначала упаковать наше приложение с помощью команды mvn package до создания фактического образа. В этом разделе мы постараемся избежать этого.
Вот Dockerfile для нашего приложения Spring Boot Hello-World, которое использует многоступенчатую сборку. Позвольте мне объяснить Dockerfile. Я использовал образ maven-openjdk11 для сборки и создания jar-файла для моего проекта на первом этапе, но это не будет окончательный результат. На втором этапе я скопировал jar, который мы создали на предыдущем этапе сборки, и создал новый окончательный образ на основе значительно меньшего базового образа Java 11 JRE. Окончательный образ Docker не включает JDK или maven, а только JRE. Если вы заметили, время сборки здесь больше, потому что все необходимые зависимости должны быть загружены на первом этапе сборки. Думаю, это единственный недостаток такого подхода.
Размер образа при многоступенчатой сборке Docker.
Ниже показано использование памяти после запуска контейнера Docker нашего приложения Spring Boot Hello-World.
Сравнение данных
В этом разделе Dive будет использоваться для проверки слоев образов, созданных с использованием методов контейнеризации, которые мы рассмотрели в этой статье. Dive достаточно умен, чтобы понять, тратите ли вы какое-либо пространство, и если да, то вы можете найти способы уменьшить размер образа Docker / OCI.
Мы оценили предложения на основе того, насколько они соответствуют каждому из критериев, указанных в следующем разделе.
Критерий первый: простота использования
Как Jib, так и Spring Boot Buildpack методы просты. С ними легко начать, просто добавив плагин. Они встроены в экосистему Spring Boot. Они действительно предоставляют некоторые разумные настройки по умолчанию для работы, и вам решать, какой уровень настройки вы ожидаете. Однако эти два параметра могут не поддерживать все функции, которые выполняет Dockerfile, например, использование чего-то вроде RUN-эквивалента инструкции Dockerfile с Jib или Buildpack. Docker требует отдельной установки, и вам необходимо ознакомиться с командами, которые он поддерживает. Как мы видели ранее, мы также должны следовать некоторым рекомендациям Docker, чтобы создать более тонкий образ для нашего приложения. Однако Jib предоставляет (по умолчанию) базовые образы без дистрибутива, которые легче и безопаснее, поскольку они не
Критерий второй: время создания образа
33 секунды при первом запуске сборки, а последующие сборки были еще быстрее. Ни один из других вариантов, которые мы исследовали, не подходит.
Критерий третий: использование ресурсов
Поддержка Spring Boot Jib обеспечивает некоторые разумные настройки по умолчанию, а его базовый образ без дистрибутива намного меньше, чем другие варианты, что приводит к окончательному меньшему образу. Docker не такой уж тонкий по сравнению с Jib, даже при многоступенчатой сборке с тонким базовым образом. Образ, созданный с помощью поддержки Buildpack для Spring Boot, велик по сравнению с многоступенчатой сборкой Jib и Docker. Наконец, Jib потребляет меньше всего памяти.
Обзор критериев: слои образа
В приведенном выше разделе сравнения слоев образов вы можете увидеть, что простые и многоступенчатые образы сборки Docker объединяют зависимости, ресурсы и классы в один неэффективный слой. Кроме того, есть пустая трата времени, которую можно улучшить. С помощью Jib мы расширили структуру каталогов для классов, ресурсов и зависимостей, и их размер минимален. Преимущество этого подхода в том, что при любых изменениях кода перестраиваются только ваши изменения, а не все приложение. Это означает, что Jib толкает только слой, который изменяется, а остальные слои остаются прежними. С Buildpack у нас более или менее такое же распределение слоев по сравнению с Jib, но есть и некоторая потеря места, так как оценка эффективности образа составляет 99%. Еще одна проблема с Buildpack заключается в том, что он объединяет ресурсы вместе, что делает разбиение на уровни неэффективным.