Если вы когда-либо сталкивались с проблемой «это работает на моей машине», Docker может быть решением.

Введение

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

Контейнер против виртуальной машины

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

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

В целом основными преимуществами Docker по сравнению с виртуальными машинами являются:

  • Быстрый запуск: не нужно загружать операционную систему.
  • Изоляция: каждая служба изолирована в своем собственном контейнере со своими зависимостями.
  • Переносимость: после того, как служба помещена в контейнер, контейнер можно легко переместить в другую инфраструктуру или системы других людей.

Компоненты Докера

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

Докер Двигатель

Каждая технология контейнеризации нуждается в механизме контейнеров. Контейнерный движок — это часть программного обеспечения, которое используется для управления контейнерами, принятия пользовательского ввода и обработки изображений или других объектов контейнеризации. Одним из примеров ядра контейнера является Docker Engine. Он состоит из трех частей:

  • Docker Daemon dockerd: управляет такими объектами, как изображения и контейнеры.
  • Docker API: RESTful API используется для связи с dockerd
  • Docker CLI: интерфейс командной строки для Docker

Подробности об установке Docker Engine: Установить Docker Engine

Docker-образ

Изображение используется в качестве схемы для запуска контейнера. Он знает все, что нужно для запуска контейнера, необходимые исходные файлы и все остальное. По сути, есть два способа получить необходимое изображение:

  • Общедоступные образы Docker
  • Создание личного Dockerfile

Докерфайл

Для создания персональных образов для докеризации собственных приложений используются Dockerfiles. Dockerfile — это текстовый файл, который используется для определения команд, которые пользователь будет вызывать в командной строке для создания образа, что будет описано позже. В следующем примере показано, как контейнеризировать приложение NodeJS. Ключевое слово FROM определяет базовое изображение нашего изображения. В этом случае базовым образом является node:16, который предлагает все необходимое для контейнеризации приложения NodeJS. Например, базовый образ также может быть mysql для запуска базы данных MySQL в контейнере. Docker Hub предлагает широкий спектр образов, которые можно использовать напрямую или использовать в качестве базового образа в вашем Dockerfile. После определения базового образа выполняются следующие шаги:

  1. Создание каталога /app и определение его как рабочего каталога
  2. COPY локального файла package.json в текущий рабочий каталог контейнера
  3. Установка npm-пакетов, определенных в package.json
  4. COPY необходимых исходных файлов в текущий рабочий каталог
  5. CMD определяет команду, которая выполняется при запуске контейнера

Процесс создания образа из Dockerfile называется сборкой. Команда docker build -t <Tag> . создаст Dockerfile. Флаг -t используется для пометки изображения, что в основном дает имя Dockerfile. . в конце определяет путь к Dockerfile, который в данном случае является текущим каталогом.

Дополнительные команды, которые можно использовать в Dockerfiles, и их описание можно найти в Справочнике по Dockerfile.

.dockerignore

Файл .dockerignore можно использовать для игнорирования файлов во время сборки. Это может понадобиться, если вы хотите игнорировать свой node_modulesили аналогичный. Следовательно, потребуется файл с именем .dockerignore, содержащий файлы, которые следует игнорировать. В следующем примере каталоги .git и node_modules игнорируются.

Подробности о синтаксисе можно найти здесь: Файл .dockerignore

Реестр

Реестр в терминах Docker используется для хранения, управления и предоставления образов. Примером публичного реестра является уже упомянутый Dockerhub. Google также предлагает собственный реестр контейнеров: Google-Container-Registry. Если Gitlab уже используется для контроля версий, его также можно использовать в качестве реестра контейнеров, поскольку он предлагает эту функцию. В дополнение к общедоступным реестрам могут быть развернуты персональные реестры. Это можно сделать с помощью образа реестра, предлагаемого непосредственно Docker.

Наслоение изображения

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

Изображение можно проанализировать с помощью команды docker history <Name>. Для ранее описанного образа NodeJS вывод будет следующим:

Смотрите вторую часть серии: