Если вы спешите, ознакомьтесь с разделом TLDR в конце статьи.

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

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

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

Вот где в игру вступает контейнеризация.

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

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

Знакомство с контейнерами

Концепция контейнеров уходит своими корнями в операционную систему Linux, в частности, в функцию под названием «Контейнеры Linux» или «LXC». LXC — это технология, обеспечивающая виртуализацию на уровне операционной системы, позволяющая запускать несколько изолированных сред Linux (контейнеров) на одном хост-компьютере.

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

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

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

Коротко об изображениях

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

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

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

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

Давайте быстро взглянем на базовый пример Dockerfile, который запускает универсальное приложение Python 3.9:

# Specify the parent image to use as the starting point. 
# In this case, it's a Python 3.9 image
FROM python:3.9

# Set the working directory within the container to /app. 
# This is where the incoming instructions will be executed.
WORKDIR /app

# Copy the requirements file from the the host to the current working
# directory in the container (. refers to the current directory).
COPY requirements.txt .

# Install the dependencies 
# The '--no-cache-dir' option disables the cache, which helps reducing
# the size of the Docker image
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code to the container
COPY . .

# Specify the command to run when the container starts
CMD ["python", "app.py"]

Как видите, если мы удалим строки комментариев, мы сможем подготовить определение образа Docker для приложения Python всего в 6 строках текста. Это довольно круто, если вы спросите меня!

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

В приведенном выше примере первая команда извлекает образ Python 3.9 в качестве отправной точки для нашего образа, поэтому в нашей среде уже будет установлен Python. Но откуда взялся этот образ Python?

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

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

  • Три команды, которые вы видите внизу (docker run, docker build и docker pull), на самом деле являются командами Docker. Это инструкции из интерфейса командной строки Docker для управления контейнерами и образами. Например, «сборка докеров» используется для создания образа, поэтому вы видите, что стрелка от команды идет прямо к прямоугольнику «Образы Docker». Наоборот, «docker pull» используется для извлечения образов из Docker Hub непосредственно в пул образов Docker на хосте.
  • Демон Docker — это фоновый процесс, работающий на хост-компьютере. Он управляет контейнерами и образами Docker, обрабатывая запросы от интерфейса командной строки Docker. Демон взаимодействует со средами выполнения контейнеров (например, containerd) и ядром хост-ОС для создания контейнеров и управления ими, обеспечивая надлежащую изоляцию и управление ресурсами.

Но довольно сложных вещей, на это есть время.

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

Когда дело касается образов Docker, вы редко начинаете с нуля. В Docker Hub есть множество официальных и неофициальных образов, которые приходят на помощь с готовыми средами, которые вы можете извлечь и использовать в качестве «родительского образа», а затем расширять их. Мы только что сделали это в нашем примере — «python: 3.9» — это родительский образ для нашего пользовательского образа Docker. Когда мы создадим этот образ Docker, механизм Docker позаботится о первой строке нашего файла Docker, извлекая официальный образ «python: 3.9» из концентратора Docker, а затем продолжит создание следующих слоев нашего образа на основе этого. начальная точка Python 3.9.

TLDR для чайников

  • Docker — это программное обеспечение, которое позволяет упаковывать ваши приложения и все, что им нужно для работы, чтобы вы могли легко перемещать их на разные компьютеры или запускать в облаке без каких-либо головных болей. Это все равно, что поместить свое приложение на крошечный портативный компьютер, который везде работает одинаково.
  • Контейнер Docker — это независимое и изолированное пространство на вашем компьютере, где вы можете запускать свое приложение вместе со всем, что ему нужно для правильной работы. На самом деле это процесс, который выполняется на вашем компьютере, но создается впечатление, что внутри вашего компьютера находится мини-компьютер, специально настроенный только для вашего приложения.
  • Образ Docker похож на карту рецептов для вашего приложения. Он содержит все инструкции и ингредиенты, необходимые для создания нескольких контейнеров, точно так же, как карточка рецепта печенья позволяет вам делать партии печенья, которые будут идентичными во всех возможных смыслах.
  • Чтобы создать образ Docker, вам нужно определить список пошаговых инструкций, которые сообщат вашему компьютеру, как подготовить и настроить все, что нужно вашему приложению для бесперебойной работы внутри контейнера Docker. Это Dockerfile. Это все равно, что рассказать Docker, как создать вашу персонализированную среду. (например, Шаг 1 — Создайте среду на основе Ubuntu, Шаг 2 — Установите python и обновите pip и т. д. до тех пор, пока вы не запустите свое приложение)
  • Обычно вы можете писать свои образы Docker, начиная с работы, которую уже сделал кто-то другой. Не нужно изобретать велосипед. Вы можете получить тысячи предварительно созданных образов из реестров Docker, онлайн-библиотек, где вы можете заимствовать все виды готовых к использованию настроек приложений, экономя ваше время и усилия при их создании с нуля. Вы даже можете загружать свои собственные рецепты в онлайн-реестры. Официальный общедоступный реестр Docker называется Docker Hub.