Принципы работы образов Docker
Помните, что образ контейнера становится единицей, которую мы используем для распространения приложений. Мы также упомянули, что контейнер находится в стандартизованном формате, который используются как нашими разработчиками, так и командами операций.
Здесь мы рассмотрим различия между программным обеспечением, пакетами и изображениями, которые используются в Docker. Знание различий между этими понятиями поможет нам лучше понять, как работают образы Docker.
Мы также кратко рассмотрим функции ОС узла и ОС, работающей в контейнере.
Программное обеспечение, упакованное в контейнер
Программное обеспечение, упаковаемое в контейнер, не ограничивается приложениями, которые создаются нашими разработчиками. Под программным обеспечением мы будем понимать код приложения, системные пакеты, двоичные файлы, библиотеки, файлы конфигурации и операционную систему, работающую в контейнере.
Например, предположим, что мы разрабатываем портал отслеживания заказов для использования различных точек нашей компании. Нам нужно рассмотреть полный стек программного обеспечения, применяемого для выполнения этого веб-приложения. Приложение, которое мы создаем, — это приложение MVC .NET Core, и мы планируем развернуть приложение с помощью nginx в качестве обратного прокси-сервера в Ubuntu Linux. Все эти программные компоненты входят в образ контейнера.
Что такое образ контейнера?
Образ контейнера — это переносимый пакет, содержащий программное обеспечение. При запуске он становится контейнером. Контейнер — это экземпляр образа в памяти.
Образ контейнера является неизменяемым. После создания образа его нельзя изменить. Единственный способ изменить образ — создать новый. Эта особенность дает гарантию того, что образ, используемый в рабочей среде, полностью совпадает с образом, который применялся при разработке и контроле качества.
Что такое ОС узла?
ОС узла — это ОС, в которой выполняется модуль Docker. Контейнеры Docker, работающие в Linux, совместно используют ядро ос узла и не требуют ос контейнера, если двоичный файл может напрямую получить доступ к ядру ОС.
Однако контейнеры Windows нуждаются в ОС контейнера. Контейнер полагается на ядро ОС для управления службами, такими как файловая система, сеть, планирование процессов и управление памятью.
Что такое ОС контейнера?
Ос контейнера — это ОС, которая является частью упаковаемого образа. У нас есть гибкость для включения различных версий операционных систем Linux или Windows в контейнер. Эта гибкость позволяет нам получить доступ к определенным функциям ОС или установить дополнительное программное обеспечение, которое могут использовать наши приложения.
Ос контейнера изолирована от ос узла, и это среда, в которой мы развертываем и запускаем наше приложение. В сочетании с неизменностью образа такая изоляция означает, что среда для приложения на этапе разработки аналогична рабочей среде.
В нашем примере мы используем Ubuntu Linux в качестве ОС контейнера, и эта ОС не меняется на разработку или рабочую среду. Образ всегда один и тот же.
Что такое стековая файловая система унификации (Unionfs
)?
Мы используем Unionfs
для создания образов Docker. Unionfs
представляет собой файловую систему, которая позволяет стекать несколько каталогов , называемых ветвями, таким образом, чтобы он отображался так, как если бы содержимое объединено. Однако на физическом уровне оно хранится раздельно. Unionfs
позволяет добавлять и удалять ветви в процессе построения файловой системы.
Например, предположим, что мы создаем образ для описанного выше веб-приложения. Мы расположим дистрибутив Ubuntu как базовый образ поверх файловой системы загрузки. Затем мы установим nginx и наше веб-приложение. Мы эффективно отстраним nginx и веб-приложение на основе исходного образа Ubuntu.
Последний доступный для записи слой создается после запуска контейнера из образа. Однако этот слой не сохраняется при уничтожении контейнера.
Что такое базовый образ?
Базовый образ использует образ Docker scratch
. scratch
— это пустой образ контейнера, который не создает слой файловой системы. Он предполагает, что запускаемое приложение может напрямую использовать ядро ОС узла.
Что такое родительский образ?
Родительский образ — это образ контейнера, из которого создаются образы.
Например, вместо создания образа из scratch
Ubuntu мы будем использовать образ, уже основанный на Ubuntu. Мы даже можем использовать образ, уже установленный nginx. Родительский образ обычно включает в себя ОС контейнера.
В чем основное различие между базовым и родительским образами?
Оба типа образов позволяют создавать многократно используемые образы. Однако базовые образы позволяют нам больше контролировать окончательное содержимое изображения. Напомним, что изображение неизменяемо; вы можете добавлять только к изображению, а не вычитать.
В Windows можно создавать только образы контейнеров, основанные на базовых образах контейнеров Windows. Корпорация Майкрософт предоставляет и обслуживает эти базовые образы контейнеров Windows.
Что такое Dockerfile?
Dockerfile — это текстовый файл с инструкциями, используемыми для сборки и запуска образа Docker. Он определяет следующие аспекты изображения:
- базовый или родительский образ, используемый для создания образа;
- команды для обновления базовой ОС и установки дополнительного программного обеспечения;
- включаемые артефакты сборки, например разрабатываемое приложение;
- Предоставляемые службы, такие как хранилище и конфигурация сети
- команда, выполняемая при запуске контейнера.
Сопоставим эти аспекты с примером файла Dockerfile. Предположим, что мы создаем образ Docker для веб-сайта ASP.NET Core. Файл Dockerfile может выглядеть следующим образом:
# Step 1: Specify the parent image for the new image
FROM ubuntu:18.04
# Step 2: Update OS packages and install additional software
RUN apt -y update && apt install -y wget nginx software-properties-common apt-transport-https \
&& wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \
&& dpkg -i packages-microsoft-prod.deb \
&& add-apt-repository universe \
&& apt -y update \
&& apt install -y dotnet-sdk-3.0
# Step 3: Configure Nginx environment
CMD service nginx start
# Step 4: Configure Nginx environment
COPY ./default /etc/nginx/sites-available/default
# STEP 5: Configure work directory
WORKDIR /app
# STEP 6: Copy website code to container
COPY ./website/. .
# STEP 7: Configure network requirements
EXPOSE 80:8080
# STEP 8: Define the entry point of the process that runs in the container
ENTRYPOINT ["dotnet", "website.dll"]
Мы не рассмотрим спецификацию файла Dockerfile здесь или подробные сведения о каждой команде в предыдущем примере. Однако обратите внимание, что в этом файле есть несколько команд, позволяющих управлять структурой изображений. Например, COPY
команда копирует содержимое из определенной папки на локальном компьютере в образ контейнера, который мы создаем.
Напомним, что ранее мы упомянули, что образы Docker используют unionfs
. На каждом этапе в процессе создания окончательного образа контейнера создается кэшированный образ контейнера. Эти временные изображения сложены поверх предыдущего изображения и представлены как одно изображение после завершения всех шагов.
Наконец, обратите внимание на последний шаг (8). Элемент ENTRYPOINT
в файле указывает, какой процесс будет выполняться при запуске контейнера из образа. Если не выполняется входная точка или другой процесс, Docker интерпретирует это как нет ничего для контейнера, и контейнер завершит работу.
Управление образами Docker
Образы Docker — это большие файлы, которые изначально хранятся на компьютере, и нам нужны инструменты для управления этими файлами.
Интерфейс командной строки Docker и Docker Desktop позволяют управлять изображениями, создавая, перечисляя, удаляя и запуская их. Управление образами Docker производится с помощью клиента docker
. Клиент не выполняет команды напрямую и отправляет все запросы в управляющая dockerd
программа.
Здесь мы не будем рассматривать все команды клиента и их флаги, а ограничимся лишь некоторыми наиболее часто используемыми. Дополнительные сведения в уроке сводки этого модуля содержат ссылки на документацию По Docker, которая подробно охватывает все команды и флаги команд.
Сборка образа
Для сборки образов Docker служит команда docker build
. Предположим, что для сборки образа мы используем приведенное выше определение Dockerfile. Ниже приведен пример, показывающий команду сборки:
docker build -t temp-ubuntu .
Ниже приведены выходные данные команды сборки:
Sending build context to Docker daemon 4.69MB
Step 1/8 : FROM ubuntu:18.04
---> a2a15febcdf3
Step 2/8 : RUN apt -y update && apt install -y wget nginx software-properties-common apt-transport-https && wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && dpkg -i packages-microsoft-prod.deb && add-apt-repository universe && apt -y update && apt install -y dotnet-sdk-3.0
---> Using cache
---> feb452bac55a
Step 3/8 : CMD service nginx start
---> Using cache
---> ce3fd40bd13c
Step 4/8 : COPY ./default /etc/nginx/sites-available/default
---> 97ff0c042b03
Step 5/8 : WORKDIR /app
---> Running in 883f8dc5dcce
Removing intermediate container 883f8dc5dcce
---> 6e36758d40b1
Step 6/8 : COPY ./website/. .
---> bfe84cc406a4
Step 7/8 : EXPOSE 80:8080
---> Running in b611a87425f2
Removing intermediate container b611a87425f2
---> 209b54a9567f
Step 8/8 : ENTRYPOINT ["dotnet", "website.dll"]
---> Running in ea2efbc6c375
Removing intermediate container ea2efbc6c375
---> f982892ea056
Successfully built f982892ea056
Successfully tagged temp-ubuntu:latest
Не беспокойтесь, если вы не понимаете предыдущие выходные данные. Однако обратите внимание на шаги в них. Когда выполняется каждый из них, к создаваемому образу добавляется новый слой.
Кроме того, обратите внимание на то, что выполняется ряд команд для установки программного обеспечения и управления конфигурацией. Например, на шаге 2 выполняются команды apt -y update
и apt install -y
для обновления операционной системы. Эти команды выполняются в работающем контейнере, созданном для этого шага. После выполнения команды промежуточный контейнер удаляется. Базовый кэшированный образ сохраняется в узле сборки и не удаляется автоматически. Благодаря такой оптимизации при последующей сборке эти образы будут использоваться повторно для ускорения процесса.
Что такое тег образа?
Тег изображения — это текстовая строка, используемая для версии изображения.
В предыдущем примере сборки обратите внимание на последнее сообщение: "Successfully tagged temp-ubuntu: latest" (Успешно применен тег temp-ubuntu: latest). При сборке образа мы присваиваем ему имя и при необходимости добавляем тег с помощью флага команды -t
. В примере мы присвоили образу имя с помощью флага -t temp-ubuntu
, но в итоге получилось имя temp-ubuntu: latest. Тег latest
применяется, если иной тег не указан явно.
Одному образу можно назначить несколько тегов. По соглашению самой последней версии образа назначаются тег latest и тег, описывающий номер версии образа. При выпуске новой версии образа можно переназначить тег latest, чтобы он ссылался на новый образ.
Для Windows корпорация Майкрософт не предоставляет базовые образы контейнеров с последним тегом. Для базовых образов контейнеров Windows необходимо указать тег, который вы хотите использовать. Например, базовый образ контейнера Windows для Server Core .mcr.microsoft.com/windows/servercore
Среди его тегов есть ltsc2016
, ltsc2019
и ltsc2022
.
Ниже приведен еще один пример. Предположим, что вы хотите использовать образцы образов Docker для .NET Core. Здесь у нас есть четыре версии платформ, из которых можно выбрать:
mcr.microsoft.com/dotnet/core/samples:dotnetapp
mcr.microsoft.com/dotnet/core/samples:aspnetapp
mcr.microsoft.com/dotnet/core/samples:wcfservice
mcr.microsoft.com/dotnet/core/samples:wcfclient
В приведенном выше списке изображений мы видим, что корпорация Майкрософт предоставляет несколько примеров .NET Core. Теги указывают, к каким образцам относится изображение: ASP.NET, служба WCF и т. д.
Вывод списка образов
Программное обеспечение Docker автоматически настраивает локальный реестр образов на компьютере. Вы можете просмотреть образы в реестре с помощью команды docker images
.
docker images
Выходные данные выглядят так:
REPOSITORY TAG IMAGE ID CREATED SIZE
tmp-ubuntu latest f89469694960 14 minutes ago 1.69GB
tmp-ubuntu version-1.0 f89469694960 14 minutes ago 1.69GB
ubuntu 18.04 a2a15febcdf3 5 weeks ago 64.2MB
Обратите внимание на то, что для каждого образа указывается имя, тег и идентификатор. Как вы помните, к образу можно применить несколько меток. В предыдущем выходных данных показан пример; Несмотря на то, что имена изображений отличаются, мы видим, что идентификаторы одинаковы.
Идентификаторы — это удобный способ распознания образов, которые невозможно различить по имени или тегу.
Удаление образа
Вы можете удалить образ из локального реестра Docker с помощью команды docker rmi
. Это полезно, если вам нужно сэкономить место на диске узла контейнера, так как слои образов контейнера добавляются в общее доступное пространство.
Укажите имя или идентификатор образа, который требуется удалить. В этом примере образ для образца веб-приложения удаляется по имени:
docker rmi temp-ubuntu:version-1.0
Невозможно удалить изображение, если контейнер по-прежнему использует образ. Команда docker rmi
возвращает сообщение об ошибке, которое перечисляет контейнер, основанный на образе.
Мы изучили основы образов Docker, как управлять этими изображениями и как запускать контейнер из образа. Далее мы рассмотрим, как управлять контейнерами.