Какая файловая система docker

Обновлено: 07.07.2024

layer.digest - это дайджест изображения, а не diff_id или chainId слоя, если формат упаковки - tar, дайджест равен diff_id
3. В соответствии с идентификатором найдите, есть ли локально изображение с таким же идентификатором.
4. Если нет, он отправит запрос на сервер реестра (который содержит sha256 и тип носителя файла конфигурации) и получит файл конфигурации образа (Image Config)

  1. В соответствии с diff_ids в файле конфигурации (каждый diffid соответствует sha256 пакета tar слоя, пакет tar эквивалентен исходному формату слоя), найдите, существует ли соответствующий слой локально
  2. Если слой не существует, в соответствии с sha256 и типом носителя уровня в манифесте, перейдите на сервер, чтобы получить соответствующий уровень (эквивалентно получению пакета в сжатом формате) (тип носителя: header.Set ("Accept", "application / vnd.docker.distribution) .manifest.v2 + json ”))
  3. Получив его, разархивируйте его и проверьте, соответствует ли sha256 пакета tar после распаковки diff_id в файле конфигурации (Image Config).
  4. В соответствии с типом фоновой файловой системы, используемой docker, распакуйте пакет tar и поместите его в указанный каталог
  5. После того, как все слои загружены, все изображение загружено и готово к использованию.

Что такое зеркалирование

docker daemon、docker docker

  • Образ Docker является шаблоном Docker-контейнера только для чтения, который содержит структуру файловой системы и его содержимое, необходимое для запуска Docker-контейнера, поэтому он является основой для запуска Docker-контейнера. Содержимое файла образа Docker и некоторые файлы конфигурации, которые запускают Docker-контейнер, составляют статическую операционную среду файловой системы Docker-контейнера: rootfs.
  • rootfs: Файловая система, которая видна внутренним процессам при запуске docker-контейнера, то есть корневой каталог docker-контейнера. rootfs обычно содержит файловую систему, необходимую операционной системе, например, она может включать систему каталогов в типичной Unix-подобной операционной системе, такой как / dev, / proc, / bin, / etc, / lib, / usr, / tmp и run Файлы конфигурации, инструменты и т. Д., Необходимые для контейнера Docker.
  • Когда демон docker монтирует rootfs для контейнера docker, он следует методу запуска ядра Linux, то есть устанавливает rootfs в режим только для чтения. После того, как монтирование завершено, используйте технологию монтирования объединения, чтобы смонтировать другой слой для чтения и записи в существующих rootfs только для чтения. Таким образом, читаемый и доступный для записи слой находится наверху файловой системы контейнера-докера, и под ним может быть смонтировано несколько слоев только для чтения.Изменено содержимое файла только при изменении файловой системы во время операции контейнера-докера. Запись в слой для чтения и записи и скрытие файлов старых версий в слое только для чтения.

Основные особенности изображения Docker

  • Слои: Слои достигают эффекта разделения зеркального слоя между контейнером и зеркалом. Docker commit добавляет новое изображение над этим слоем изображения
  • Копирование при записи: все контейнеры совместно используют одни и те же данные. Только когда файловая система изменится во время работы док-контейнера, измененное содержимое файла будет записано в слой для чтения и записи, а старые версии файлов будут скрыты в слое только для чтения. Копирование при записи в сочетании с многоуровневым механизмом уменьшает дисковое пространство, занимаемое образом, и время запуска контейнера.
  • Адресация содержимого: новая модель вычисляет контрольную сумму содержимого зеркального слоя, генерирует значение хеш-содержимого и использует это хеш-значение для замены предыдущего UUID в качестве уникального идентификатора зеркального уровня. Этот механизм в основном повышает безопасность изображения. (Кэш-идентификатор)
  • Совместное монтирование: технология совместного монтирования позволяет монтировать несколько файловых систем одновременно в точке монтирования и интегрировать исходный каталог точки монтирования с подключенным содержимым, так что конечная видимая файловая система будет содержать все Слой файлов и каталогов. Совместное монтирование - это способ монтирования файловых систем из нескольких слоев изображений в точку монтирования для получения унифицированного представления файловой системы, а также для драйверов хранения нижнего уровня (aufs, overlay и т. Д.) Для реализации многоуровневого объединения.

Основные понятия в изображениях Docker

  • Реестр: Реестр используется для сохранения образа докера, который также включает иерархию изображений и метаданные об изображении.
  • репозиторий: реестр - это коллекция репозитория, а репозиторий - это коллекция зеркал.
  • manifest: manifest (файл описания) в основном существует в реестре как файл метаданных образа докера, а также как файл описания структуры изображения и базовой информации во время процессов извлечения, отправки, сохранения и загрузки.
  • image: Он используется для хранения набора информации метаданных, связанных с изображением, в основном, включая архитектуру изображения (например, amd64), информацию о конфигурации изображения по умолчанию, информацию о конфигурации контейнера для построения изображения и * * rootfs, содержащие всю информацию об уровне изображения. Docker использует diff_id в rootfs для вычисления индекса адресации содержимого (chainID), чтобы получить информацию, относящуюся к слою, а затем получить содержимое файла каждого зеркального слоя.
  • layer: слой в управлении изображениями Docker в основном хранит содержимое слоя изображения, например diff_id, size, cache-id и parent. Фактическое содержимое файла управляется драйвером хранилища и может быть проиндексировано локально по cache-id.

Введение в ключевые моменты зеркалирования

repository

repository

  • Введение:docker.elastic.co/elasticsearch/elasticsearch эластичный поиск / эластичный поиск является хранилищем
  • Расположение: /var/lib/docker/image/<graph_driver>/repositories.json
  • В настоящее время докер использует алгоритм SHA256 по умолчанию для вычисления идентификатора зеркала на основе файла конфигурации метаданных зеркала. Две записи на изображении выше по существу одинаковы, вторая запись и первая запись указывают на один и тот же идентификатор зеркала. Где sha256: c8c275751219dadad8fa56b3ac41ca6cb22219ff117ca98fe82b42f24e1ba64e называется сводкой зеркала
  • Дайджест изображения: SHA256 расчет содержания манифеста изображения
  • Для локально генерируемых изображений, поскольку они не загружены в реестр, дайджест отсутствует, поскольку манифест изображения генерируется реестром.

manifest

  • Введение: Манифест также является файлом json, а тип носителя содержит описание предыдущих слоев и конфигурацию изображения для этого файла.
  • Расположение: Нет
  • Этот файл фактически является описанием реестра, он будет автоматически удален после завершения загрузки зеркала.

Image Config

  • Введение: файл json содержит описание этого изображения
  • Расположение: / var / lib / docker / image / <graph_driver> / imagedb / content / sha256 / <image_id>

  • Существуют формулы преобразования для diffId и chainId
  • sha256 /var/lib/docker/image/<graph_driver>/imagedb/content/sha256/<image_id> image_id

layer

метаданные слоя
  • Расположение: / var / lib / docker / image / <graph_driver> / layerdb / sha256 //
  • Уровень содержит изменения на предыдущем уровне, который в основном включает три аспекта:
    1) Тип изменения: был ли файл добавлен, изменен или удален
    2) Тип файла: в каком типе файлов происходит каждое изменение
    3) Атрибуты файла: время изменения файла, идентификатор пользователя, идентификатор группы, разрешения RWX и т. д.
  • Метод расчета chainID
    1) Если зеркальный слой является нижним слоем (родительский зеркальный слой отсутствует), diffID этого слоя является chainID.
    2) Формула вычисления chainID зеркального слоя имеет вид chainID (n) = SHA256 (chain (n-1) diffID (n)), который должен добавить chainID в соответствии с chainID родительского зеркального слоя Пробел и diffID текущего слоя, а затем вычислите контрольный код SHA256.
  • chche-id: случайно сгенерированный этой машиной uuid используется для идентификации уникальной на этой машине
  • diff: diffId
  • parent: chainId родительского уровня
  • размер: размер этого слоя
Соответствие между слоем diffId и дайджестом
  • Дайджест можно посмотреть, когда тянуть докер

① diffid-by-digest: сохранить соответствие между digest и diffid
② v2metadata-by-diffid: сохранить соответствие между diffid и digest

данные слоя

Расположение: / var / lib / docker / <graph_driver>

Вывод

Эта статья знакомит с локальным хранилищем изображений, включая две директории / var / lib / docker / image и / var / lib / docker / aufs, но в каталоге / var / lib / docker / image есть две директории Предполагает:

/ var / lib / docker / image / aufs / imagedb / metadata: в нем хранится некоторая информация о локальном изображении, изображение, полученное с сервера, не сохраняет данные в этот каталог,

/ var / lib / docker / image / aufs / layerdb / mounts: при создании контейнера docker создаст новый слой для каждого контейнера на основе изображения /etc/resolv.conf и другие файлы, информация о слое, созданная этим слоем, находится здесь.

Интеллектуальная рекомендация


Michael.W Поговорите о Hyperledger Fabric. Проблема 20 - Подробная индивидуальная сортировка узла с пятью порядками с исходным кодом для чтения.

Michael.W Поговорите о Hyperledger Fabric. Проблема 20 - Подробная индивидуальная сортировка узла с пятью порядками с исходным кодом чтения Fabric Файл исходного кода одиночного режима находится в ord.


Мяу Пасс Матрица SDUT

Мяу Пасс Матрица SDUT Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Problem Description Лянцзян получил матрицу, но эта матрица была особенно уродливой, и Лянцзян испытал отвращение. Чт.


Гессенская легкая двоичная структура удаленного вызова

Hessian - это легкая двоичная структура удаленного вызова, официальный адрес документа, в основном он включает протокол удаленного вызова Hessian, протокол сериализации Hessian, прокси-сервер клиента .


TCP Pasket и распаковка и Нетти Solutions

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


Создавать, запускать, просматривать, перемещать контейнеры и образы с помощью интерфейса командной строки Docker (Docker CLI) проще простого, но задумывались ли вы когда-нибудь, как на самом деле работают внутренние компоненты, обеспечивающие работу интерфейса Docker? За этим простым интерфейсом скрывается множество продвинутых технологий, и специально к старту нового потока курса по DevOps в этой статье мы рассмотрим одну из них — объединённую файловую систему, используемую во всех слоях контейнеров и образов. Маститым знатокам контейнеризации и оркестрации данный материал навряд ли откроет что-то новое, зато будет полезен тем, кто делает первые шаги в DevOps.

Что такое объединённая файловая система?

Каскадно-объединённое монтирование — это тип файловой системы, в которой создается иллюзия объединения содержимого нескольких каталогов в один без изменения исходных (физических) источников. Такой подход может оказаться полезным, если имеются связанные наборы файлов, хранящиеся в разных местах или на разных носителях, но отображать их надо как единое и совокупное целое. Например, набор пользовательских/корневых каталогов, расположенных на удалённых NFS-серверах, можно свести в один каталог или можно объединить разбитый на части ISO-образ в один целый образ.

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

aufs — альтернативная версия исходной файловой системы UnionFS с добавлением множества новых функций. Данную файловую систему нельзя использовать в составе ванильного ядра Linux. Aufs использовалась в качестве файловой системы по умолчанию для Docker на Ubuntu/Debian, однако со временем она была заменена на OverlayFS (для ядра Linux >4.0). По сравнению с другими объединёнными файловыми системами эта система имеет ряд преимуществ, описанных в Docker Docs.

Следующая система — OverlayFS — была включена в ядро Linux Kernel, начиная с версии 3.18 (26 октября 2014 года). Данная файловая система используется по умолчанию драйвером overlay2 Docker (это можно проверить, запустив команду docker system info | grep Storage). Данная файловая система в целом обеспечивает лучшую, чем aufs, производительность и имеет ряд интересных функциональных особенностей, например функцию разделения страничного кэша.

ZFS — объединённая файловая система, разработанная Sun Microsystems (в настоящее время эта компания называется Oracle). В этой системе реализован ряд полезных функций, таких как функция иерархического контрольного суммирования, функция обработки снимков, функция резервного копирования/репликации или архивирования и дедупликации (исключения избыточности) внутренних данных. Однако, поскольку автором этой файловой системы является Oracle, её выпуск осуществлялся под общей лицензией на разработку и распространение (CDDL), не распространяемой на программное обеспечение с открытым исходным кодом, поэтому данная файловая система не может поставляться как часть ядра Linux. Тем не менее можно воспользоваться проектом ZFS on Linux (ZoL), который в документации Docker описывается как работоспособный и хорошо проработанный. но, увы, непригодный к промышленной эксплуатации. Если вам захочется поработать с этой файловой системой, её можно найти здесь.

Btrfs — ещё один вариант файловой системы, представляющий собой совместный проект множества компаний, в том числе SUSE, WD и Facebook. Данная файловая система выпущена под лицензией GPL и является частью ядра Linux. Btrfs — файловая система по умолчанию дистрибутива Fedora 33. В ней также реализованы некоторые полезные функции, такие как операции на уровне блоков, дефрагментация, доступные для записи снимки и множество других. Если вас не пугают трудности, связанные с переходом на специализированный драйвер устройств памяти для Docker, файловая система Btrfs с её функциональными и производительными возможностями может стать лучшим вариантом.

Если вы хотите более глубоко изучить характеристики драйверов, используемых в Docker, в Docker Docs можно ознакомиться с таблицей сравнения разных драйверов. Если вы затрудняетесь с выбором файловой системы (не сомневаюсь, есть и такие программисты, которые знают все тонкости файловых систем, но эта статья предназначена не для них), возьмите за основу файловую систему по умолчанию overlay2 — именно её я буду использовать в примерах в оставшейся части данной статьи.

Почему именно она?

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

Многие образы, используемые для запуска контейнеров, занимают довольно большой объём, например, ubuntu занимает 72 Мб, а nginx — 133 Мб. Было бы довольно разорительно выделять столько места всякий раз, когда потребуется из этих образов создать контейнер. При использовании объединённой файловой системы Docker создаёт поверх образа тонкий слой, а остальная часть образа может быть распределена между всеми контейнерами. Мы также получаем дополнительное преимущество за счёт сокращения времени запуска, так как отпадает необходимость в копировании файлов образа и данных.

Объединённая файловая система также обеспечивает изоляцию, поскольку контейнеры имеют доступ к общим слоям образа только для чтения. Если контейнерам когда-нибудь понадобится внести изменения в любой файл, доступный только для чтения, они используют стратегию копирования при записи copy-on-write (её мы обсудим чуть позже), позволяющую копировать содержимое на верхний слой, доступный для записи, где такое содержимое может быть безопасно изменено.

Как это работает?

Теперь вы вправе задать мне важный вопрос: как же это всё работает на практике? Из сказанного выше может создаться впечатление, что объединённая файловая система работает с применением некой чёрной магии, но на самом деле это не так. Сейчас я попытаюсь объяснить, как это работает в общем (неконтейнерном) случае. Предположим, нам нужно объединить два каталога (верхний и нижний) в одной точке монтирования и чтобы такие каталоги были представлены унифицированно:

В терминологии объединённого монтирования такие каталоги называются ветвями. Каждой из таких ветвей присваивается свой приоритет. Приоритет используется для того, чтобы решить, какой именно файл будет отображаться в объединённом представлении, если в нескольких исходных ветках присутствуют файлы с одним и тем же именем. Если проанализировать представленные выше файлы и каталоги, станет понятно, что такой конфликт может возникнуть, если мы попытаемся использовать их в режиме наложения (файл code.py). Давайте попробуем и посмотрим, что у нас получится:

В приведённом выше примере мы использовали команду mount с type overlay, чтобы объединить нижний каталог (только для чтения; более низкий приоритет) и верхний каталог (чтение-запись; более высокий приоритет) в объединённое представление в каталоге /mnt/merged. Мы также включили опцию workdir=./workdir. Этот каталог служит местом для подготовки объединённого представления нижнего каталога (lowerdir) и верхнего каталога (upperdir) перед их перемещением в каталог /mnt/merged.

Если посмотреть на выходные данные команды cat, можно заметить, что в объединённом представлении приоритет получили файлы верхнего каталога.

Теперь мы знаем, как объединить два каталога и что произойдёт при возникновении конфликта. Но что произойдёт, если попытаться изменить определенные файлы в объединённом представлении? Здесь в игру вступает функция копирования при записи (CoW). Что именно делает эта функция? CoW — это способ оптимизации, при котором, если две вызывающих программы обращаются к одному и тому же ресурсу, можно дать им указатель на один и тот же ресурс, не копируя его. Копирование необходимо только тогда, когда одна из вызывающих программ пытается осуществить запись собственной "копии" — отсюда в названии способа появилось слово "копия", то есть копирование осуществляется при (первой попытке) записи.

В случае объединённого монтирования это означает, что, если мы пытаемся изменить совместно используемый файл (или файл только для чтения), он вначале копируется в верхнюю ветвь, доступную для записи (upperdir), имеющую более высокий приоритет, чем нижние ветви (lowerdir), доступные только для чтения. Когда файл попадает в ветвь, доступную для записи, его можно безопасно изменить, и его новое содержимое отобразится в объединённом представлении, так как верхний слой имеет более высокий приоритет.

Последняя операция, которую мы, возможно, захотим выполнить, — это удаление файлов. Чтобы "удалить" файл, в ветви, доступной для записи, создается файл whiteout для очистки "удаляемого" файла. На самом деле файл не будет удалён физически. Вернее сказать, что он будет скрыт в объединённом представлении.

Мы много говорили о принципах объединённого монтирования, но как все эти принципы работают на платформе Docker и её контейнерах? Рассмотрим многоуровневую архитектуру Docker. Песочница контейнера состоит из нескольких ветвей образа, или, как мы их называем, слоёв. Такими слоями являются часть объединённого представления, доступная только для чтения (lowerdir), и слой контейнера — тонкая верхняя часть, доступная для записи (upperdir).

Не считая терминологических различий, речь фактически идёт об одном и том же — слои образа, извлекаемые из реестра, представляют собой lowerdir, и, если запускается контейнер, upperdir прикрепляется поверх слоев образа, обеспечивая рабочую область, доступную для записи в контейнер. Звучит довольно просто, не так ли? Давайте проверим, как всё работает!

Проверяем

Чтобы показать, как Docker использует файловую систему OverlayFS, попробуем смоделировать процесс монтирования Docker контейнеров и слоев образа. Прежде чем мы приступим, нужно вначале очистить рабочее пространство и получить образ, с которым можно работать:

Итак, у нас имеется образ (nginx), с которым можно работать, далее нужно проверить его слои. Проверить слои образа можно, либо запустив проверку образа в Docker и изучив поля GraphDriver, либо перейдя в каталог /var/lib/docker/overlay2, в котором хранятся все слои образа. Выполним обе эти операции и посмотрим, что получится:

Если внимательно посмотреть на полученные результаты, можно заметить, что они весьма похожи на те, что мы уже наблюдали после применения команды mount, не находите?

LowerDir: это каталог, в котором слои образа, доступные только для чтения, разделены двоеточиями.

MergedDir: объединённое представление всех слоев образа и контейнера.

UpperDir: слой для чтения и записи, на котором записываются изменения.

WorkDir: рабочий каталог, используемый Linux OverlayFS для подготовки объединённого представления.

Сделаем ещё один шаг — запустим контейнер и изучим его слои:

Из представленных выше выходных данных следует, что те же каталоги, которые были перечислены в выводе команды docker inspect nginx ранее как MergedDir, UpperDir и WorkDir (с id 3d963d191b2101b3406348217f4257d7374aa4b4a73b4a6dd4ab0f365d38dfbd), теперь являются частью LowerDir контейнера. В нашем случае LowerDir составляется из всех слоев образа nginx, размещённых друг на друге. Поверх них размещается слой в UpperDir, доступный для записи, содержащий каталоги /etc, /run и /var. Также, раз уж мы выше упомянули MergedDir, можно видеть всю доступную для контейнера файловую систему, в том числе всё содержимое каталогов UpperDir и LowerDir.

И, наконец, чтобы эмулировать поведение Docker, мы можем использовать эти же каталоги для ручного создания собственного объединённого представления:

В нашем случае мы просто взяли значения из предыдущего фрагмента кода и передали их в качестве соответствующих аргументов в команду mount. Разница лишь в том, что для объединённого представления вместо /var/lib/docker/overlay2/. /merged мы использовали /mnt/merged.

Именно к этому сводится действие файловой системы OverlayFS в Docker — на множестве уложенных друг на друга слоев может использоваться одна команда монтирования. Ниже приводится отвечающая за это часть кода Docker — заменяются значения lowerdir=. upperdir=. workdir=. после чего следует команда unix.Mount.

Заключение

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

В этой статье мы рассмотрели только часть архитектуры Docker — файловую систему. Есть и другие части, с которыми стоит ознакомиться более внимательно, например контрольные группы (cgroups) или пространства имен Linux. Если вы их освоите — можно уже задуматься о переходе в востребованный DevOps. А с остальными знаниями, необходимыми для данной профессии мы поможем на курсе по профессии DevOps-инженер.

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

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

  • упаковывание вашего приложения (и так же используемых компонент) в docker контейнеры;
  • раздача и доставка этих контейнеров вашим командам для разработки и тестирования;
  • выкладывания этих контейнеров на ваши продакшены, как в дата центры так и в облака.

Для чего я могу использовать docker?

Быстрое выкладывание ваших приложений

Docker прекрасно подходит для организации цикла разработки. Docker позволяет разработчикам использовать локальные контейнеры с приложениями и сервисами. Что в последствии позволяет интегрироваться с процессом постоянной интеграции и выкладывания (continuous integration and deployment workflow).

Более простое выкладывание и разворачивание

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

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

Высокие нагрузки и больше полезных нагрузок

Docker легковесен и быстр. Он предоставляет устойчивую, рентабельную альтернативу виртуальным машинам на основе гипервизора. Он особенно полезен в условиях высоких нагрузок, например, при создания собственного облака или платформа-как-сервис (platform-as-service). Но он так же полезен для маленьких и средних приложений, когда вам хочется получать больше из имеющихся ресурсов.

Главные компоненты Docker

  • Docker: платформа виртуализации с открытым кодом;
  • Docker Hub: наша платформа-как-сервис для распространения и управления docker контейнерами.

Архитектура Docker

Docker использует архитектуру клиент-сервер. Docker клиент общается с демоном Docker, который берет на себя тяжесть создания, запуска, распределения ваших контейнеров. Оба, клиент и сервер могут работать на одной системе, вы можете подключить клиент к удаленному демону docker. Клиент и сервер общаются через сокет или через RESTful API.

Docker-демон

Как показано на диаграмме, демон за пускается на хост-машине. Пользователь не взаимодействует с сервером на прямую, а использует для этого клиент.

Docker-клиент

Docker-клиент, программа docker — главный интерфейс к Docker. Она получает команды от пользователя и взаимодействует с docker-демоном.

Внутри docker-а

  • образы (images)
  • реестр (registries)
  • контейнеры

Образы

Docker-образ — это read-only шаблон. Например, образ может содержать операционку Ubuntu c Apache и приложением на ней. Образы используются для создания контейнеров. Docker позволяет легко создавать новые образы, обновлять существующие, или вы можете скачать образы созданные другими людьми. Образы — это компонента сборки docker-а.

Реестр

Docker-реестр хранит образы. Есть публичные и приватные реестры, из которых можно скачать либо загрузить образы. Публичный Docker-реестр — это Docker Hub. Там хранится огромная коллекция образов. Как вы знаете, образы могут быть созданы вами или вы можете использовать образы созданные другими. Реестры — это компонента распространения.

Контейнеры

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

Так как же работает Docker?

  • можем создавать образы, в которых находятся наши приложения;
  • можем создавать контейнеры из образов, для запуска приложений;
  • можем распространять образы через Docker Hub или другой реестр образов.

Как работает образ?

Мы уже знаем, что образ — это read-only шаблон, из которого создается контейнер. Каждый образ состоит из набора уровней. Docker использует union file system для сочетания этих уровней в один образ. Union file system позволяет файлам и директориями из разных файловых систем (разным ветвям) прозрачно накладываться, создавая когерентную файловую систему.

Одна из причин, по которой docker легковесен — это использование таких уровней. Когда вы изменяете образ, например, обновляете приложение, создается новый уровень. Так, без замены всего образа или его пересборки, как вам возможно придётся сделать с виртуальной машиной, только уровень добавляется или обновляется. И вам не нужно раздавать весь новый образ, раздается только обновление, что позволяет распространять образы проще и быстрее.

В основе каждого образа находится базовый образ. Например, ubuntu, базовый образ Ubuntu, или fedora, базовый образ дистрибутива Fedora. Так же вы можете использовать образы как базу для создания новых образов. Например, если у вас есть образ apache, вы можете использовать его как базовый образ для ваших веб-приложений.

Примечание! Docker обычно берет образы из реестра Docker Hub.

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

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

Эти инструкции хранятся в файле Dockerfile . Docker считывает это Dockerfile , когда вы собираете образ, выполняет эти инструкции, и возвращает конечный образ.

Как работает docker реестр?

Реестр — это хранилище docker образов. После создания образа вы можете опубликовать его на публичном реестре Docker Hub или на вашем личном реестре.

С помощью docker клиента вы можете искать уже опубликованные образы и скачивать их на вашу машину с docker для создания контейнеров.

Docker Hub предоставляет публичные и приватные хранилища образов. Поиск и скачивание образов из публичных хранилищ доступно для всех. Содержимое приватных хранилищ не попадает в результат поиска. И только вы и ваши пользователи могут получать эти образы и создавать из них контейнеры.

Как работает контейнер?

Контейнер состоит из операционной системы, пользовательских файлов и метаданных. Как мы знаем, каждый контейнер создается из образа. Этот образ говорит docker-у, что находится в контейнере, какой процесс запустить, когда запускается контейнер и другие конфигурационные данные. Docker образ доступен только для чтения. Когда docker запускает контейнер, он создает уровень для чтения/записи сверху образа (используя union file system, как было указано раньше), в котором может быть запущено приложение.

Что происходит, когда запускается контейнер?

Или с помощью программы docker , или с помощью RESTful API, docker клиент говорит docker демону запустить контейнер.

  • какой образ использовать для создания контейнера. В нашем случае ubuntu
  • команду которую вы хотите запустить когда контейнер будет запущен. В нашем случае /bin/bash

Что же происходит под капотом, когда мы запускаем эту команду?

  • скачивает образ ubuntu: docker проверяет наличие образа ubuntu на локальной машине, и если его нет — то скачивает его с Docker Hub. Если же образ есть, то использует его для создания контейнера;
  • создает контейнер: когда образ получен, docker использует его для создания контейнера;
  • инициализирует файловую систему и монтирует read-only уровень: контейнер создан в файловой системе и read-only уровень добавлен образ;
  • инициализирует сеть/мост: создает сетевой интерфейс, который позволяет docker-у общаться хост машиной;
  • Установка IP адреса: находит и задает адрес;
  • Запускает указанный процесс: запускает ваше приложение;
  • Обрабатывает и выдает вывод вашего приложения: подключается и логирует стандартный вход, вывод и поток ошибок вашего приложения, что бы вы могли отслеживать как работает ваше приложение.

Используемые технологии

Докер написан на Go и использует некоторые возможности ядра Linux, чтобы реализовать приведенный выше функционал.

Пространство имен(namespaces)

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

Это создает изолированный уровень, каждый аспект контейнера запущен в своем простанстве имен, и не имеет доступ к внешней системе.

  • pid: для изоляции процесса;
  • net: для управления сетевыми интерфейсами;
  • ipc: для управления IPC ресурсами. (ICP: InterProccess Communication);
  • mnt: для управления точками монтирования;
  • utc: для изолирования ядра и контроля генерации версий(UTC: Unix timesharing system).

Control groups (контрольные группы)

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

Union File System

Union File Sysem или UnionFS — это файловая система, которая работает создавая уровни, делая ее очень легковесной и быстрой. Docker использует UnionFS для создания блоков, из которых строится контейнер. Docker может использовать несколько вариантов UnionFS включая: AUFS, btrfs, vfs и DeviceMapper.

Изучаем внутреннюю работу OverlayFS — файловой системы, лежащей в основе образов и контейнеров Docker, вместе с сертифицированным специалистом по работе c Kubernetes, OpenShift, Docker и автором статьи на ITNEXT. В этой статье исследована одна из частей архитектуры Docker — файловая система для Linux. Всем поклонникам этой операционной системы на заметку.

Работать с Docker CLI довольно легко — вы просто создаете, запускаете, проверяете, извлекаете и отправляете контейнеры и образы. Но задумывались ли вы над тем, как на самом деле работают внутренние компоненты в Docker-интерфейсе?

Здесь скрывается множество интересных технологий, и в этой статье мы рассмотрим одну из них — union filesystem — файловую систему, лежащую в основе всех слоев контейнеров и образов.

Union mount — это тип файловой системы, которая создает иллюзию слияния содержимого нескольких каталогов в один без изменения исходных (физических) данных в оригинальных источниках. Это может быть полезно, когда у нас есть наборы файлов, которые хранятся в разных местах и на разных носителях, и мы хотим их объединить. Например, пользовательские директории /home с удаленных NFS-серверов — все они объединены в один каталог или в один полный ISO-образ.

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

  • UnionFS — начнем с исходной объединенной файловой системы. Похоже, что разработчики UnionFS с августа 2014 года перестали ее развивать. Больше об этом можно узнать здесь .
  • aufs — альтернативная версия UnionFS, которая располагала множеством новых функций, но была отклонена для слияния с основным ядром Linux. Aufs был дефолтным драйвером для Docker в Ubuntu/Debian, но его заменили на OverlayFS (для ядра Linux >4.0). Он имеет некоторые преимущества по сравнению с другими объединенными файловыми системами. Все они описаны в Docker docs page .
  • OverlayFS — включена в ядро Linux с версии 3.18 (26 октября 2014 года). Это файловая система, использующая дефолтный драйвер Docker overlay2 (верифицировать можно с помощью docker system info | grep Storage ). OverlayFS имеет лучшую производительность, чем aufs, и располагает некоторыми приятными функциями, такими как совместное использование кеша страниц .
  • ZFS — это объединенная файловая система, созданная Sun Microsystems (теперь Oracle). Имеет некоторые интересные функции, такие как иерархическое вычисление контрольных сумм, встроенная обработка снимков файловой системы и резервное копирование/репликация или сжатие и дедупликация данных. Но при поддержке Oracle ZFS не поддерживает лицензию CDDL и поэтому не может поставляться как часть ядра Linux. Однако можно использовать проект ZFS в Linux (ZoL), который описан в документации Docker, как годный и развивающийся, но не готовый для продакшена. Если хотите попробовать, необходимую информацию можно найти здесь .
  • Btrfs — совместный проект нескольких компаний , включая SUSE, WD или Facebook, опубликованный под лицензией GPL и являющийся частью ядра Linux. Btrfs — это дефолтная файловая система в Fedora 33. Она имеет некоторые полезные функции, такие, как операции в блоках, дефрагментацию, снимки файловой системы с возможностью записи и многое другое . Если вы действительно хотите пройти через все трудности и переключиться на нестандартный драйвер хранилища для Docker, то Btrfs с его функциями и производительностью — лучший вариант.

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

Выше была упомянута причина, по которой представленный тип файловой системы может быть полезен. Но почему именно он — хороший выбор для контейнеров и Docker в целом?

Многие образы, которые мы используем для контейнеров, имеют довольно большие размеры. К примеру, размер ubuntu 72 Мб или nginx — 133 Мб. Нецелесообразно выделять столько места каждый раз, когда мы хотим создать контейнер. Благодаря объединенной файловой системе, в Docker нужно создать только один слой поверх образа, а остальная его часть может использоваться всеми контейнерами. Это также дает дополнительное преимущество в виде сокращения времени запуска, поскольку нет необходимости копировать файлы образов и другие данные.

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

Из всего описанного выше может показаться, что Union Filesystem обладает магическими способностями, но на самом деле это не так. Давайте начнем с объяснения того, как это работает в общем (неконтейнерном) случае. Представим, что мы хотели бы объединить две директории (верхний и нижний каталоги) в одну и ту же точку монтирования и получить их объединенное представление:

В терминологии Union mount эти каталоги называются ветками. Каждой из этих веток назначается свой приоритет. Этот приоритет используется для определения того, какой файл будет отображаться в объединенном представлении в случае, если в нескольких ветках есть файлы с одинаковыми именами. Глядя на файлы и директории выше, становится ясно, что если мы попытаемся наложить их поверх, они буду конфликтовать ( файл code.py ):

В приведенном выше примере мы использовали команду mount с типом overlay , чтобы объединить lower (только для чтения, низкий приоритет) и upper (запись, высокий приоритет) каталоги в единое представление /mnt/merged . Также был включен параметр workdir=./workdir , который служит местом для подготовки объединенного представления lowerdir и upperdir перед его перемещением в /mnt/merged .

Глядя на вывод команды cat выше, можно увидеть, что содержимое файлов в upper (верхнем) каталоге имеет приоритет в объединенном представлении.

Теперь мы знаем, как объединить два каталога и что произойдет в случае конфликта. Но что произойдет, если мы попытаемся изменить некоторые файлы из объединенного представления?

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

В случае union mount это означает, что когда мы пытаемся изменить общий файл (или файл только для чтения), он сначала копируется в верхнюю доступную для записи ветку ( upperdir ), которая имеет более высокий приоритет, чем нижние ветки только для чтения ( lowerdir ). Когда файл находится в ветке с возможностью записи, его можно безопасно изменить. Его новый контент будет виден в объединенном представлении, потому что верхний слой имеет более высокий приоритет.

Последняя операция — это удаление файлов. При удалении в ветке с возможностью записи создается чистый файл. Файл, который мы хотим удалить, на самом деле не удаляется, а скорее скрывается в объединенном представлении.

Как же union mount связан с Docker и его контейнерами? Давайте посмотрим на многоуровневую архитектуру Docker. Песочница контейнера состоит из нескольких веток — или слоев. Слои доступны только для чтения ( lowerdir ) и являются частью объединенного представления, а слой контейнера — записываемой верхней частью ( upperdir ).

Слои образов, которые вы извлекаете из реестра, являются lowerdir (нижним) каталогом, а при запуске контейнера, upperdir (верхний) каталог приаттачивается к верхним слоям образов, чтобы обеспечить доступное для записи рабочее пространство для вашего контейнера. Звучит довольно просто, правда? Попробуем?

Чтобы продемонстрировать, как OverlayFS используется в Docker, попробуем имитировать то, как Docker монтирует слои образов и контейнера.

Очень похоже на то, что мы видели с командой mount , правда? Более конкретно:

  • LowerDir : каталог со слоями образов, доступных только для чтения, разделенными двоеточиями.
  • MergedDir : объединенное представление всех слоев образов и контейнера.
  • UpperDir : слой чтения-записи, на котором записываются изменения.
  • WorkDir : рабочий каталог, используемый Linux OverlayFS для подготовки объединенного представления.

Теперь давайте запустим контейнер и проверим слои:

Приведенный выше пример показывает, что те же каталоги, которые были выведены в docker inspect nginx ранее, как MergedDir , UpperDir и WorkDir (с ID 3d963d191b2101b3406348217f4257d7374aa4b4a73b4a6dd4ab0f365d38dfbd) теперь являются частью LowerDir- контейнера. Здесь LowerDir состоит из всех слоев образов nginx, наложенных друг на друга. Поверх них находится доступный для записи слой в UpperDir , который содержит /etc , /run и /var . В MergedDir находится вся файловая система, доступная для контейнера, включая все содержимое из UpperDir и LowerDir .

Чтобы имитировать поведение Docker, мы можем использовать эти же каталоги для ручного создания нашего собственного объединенного представления:

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

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

Текст для Highload перевела Ольга Змерзлая.

Highload нужны авторы технических текстов. Вы наш человек, если разбираетесь в разработке, знаете языки программирования и умеете просто писать о сложном!
Откликнуться на вакансию можно здесь .

Читайте также: