7.3 Образы контейнера и уровни файловой системы ГОСТ Р 70860—2023

7.3.1 Назначение и содержание образа ГОСТ Р 70860—2023

Образ контейнера представляет собой исполняемый пакет, который содержит все необходимое для работы ПО, например приложение или микросервис. Это может быть программный код самого приложения, среда выполнения, библиотеки, переменные среды, файлы конфигурации и другие метаданные, используемые приложением. Цель состоит в том, чтобы образ контейнера описывался самостоятельно и был инкапсулированным, в результате чего у контейнерной службы появилась бы возможность заимствовать образ контейнера и создать из него контейнер без дополнительных зависимостей от базовой системы (независимо от инфраструктуры) и независимо от содержимого образа контейнера (независимо от содержимого).

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

  • указатель образа. Метаданные «верхнего уровня», которые предназначены для образов контейнеров, поддерживающих несколько различных платформ (иногда их называют fat-мэнифестом). Если поддерживается несколько платформ, для каждой платформы существует свой собственный образ, содержащий программные компоненты, которые необходимо использовать при работе контейнера на этой платформе. По сути, указатель образа ссылается на один или несколько манифестов образов;
  • манифест образа. Содержит информацию одного образа контейнера для конкретной архитектуры процессора и ОС, состоящего из конфигурации и набора уровней;
  • расположение образа. Конкретное расположение каталогов и файлов внутри образа с метаданными об уровнях файловой системы;
  • уровни файловой системы. Одна или несколько упорядоченных файловых систем (т. е. структура каталогов и файлов) и изменения в файловой системе (удаленные или обновленные файлы). Уровни накладываются друг на друга для создания полной файловой системы в работающем контейнере (см. 7.3.2 для получения дополнительной информации об уровнях файловой системы).

Функциональные возможности указателя образа и fat-мэнифестов позволяют одному образу контейнера обеспечить поддержку образов, характерных для конкретной платформы. Платформа может содержать тип процессора (архитектура ПК), тип ОС и ее уровень. Таким образом, один образ контейнера может быть структурирован так, чтобы обеспечить доставку и развертывание одного и того же приложения на нескольких различных целевых системах.

Одно из характерных свойств метаданных контейнера, содержащихся в образах контейнеров, заключается в том, что они предоставляют расширенные функции обеспечения безопасности, призванные предотвратить подделку содержимого образа контейнера с момента его создания. Записывается длина данных, а также их дайджесты (по сути, это устойчивый к конфликтам криптографический хеш байтов данных). Соответствующими данными могут быть содержимое уровней файловой системы или элементы метаданных. Дайджест может также служить уникальным идентификатором содержимого, который также может использоваться для доступа к данным с возможностью адресации содержимого. Отдельная безопасная передача дайджеста пользователю образа контейнера позволяет проверить содержимое образа контейнера, даже если оно получено из ненадежного источника [из 7.3.1 Назначение и содержание образа ГОСТ Р 70860—2023]

7.3.2 Многоуровневая файловая система ГОСТ Р 70860—2023

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

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

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

В качестве примера рассмотрим приложение node.js. Программный код приложения node.js может находиться в файле сценария app.js, а также в других файлах сценария, файлах данных и файлах конфигурации. Приложение node.js имеет зависимость от среды выполнения node.js и ряда (внешних) пакетов. В свою очередь, среда выполнения node.js зависит от различных библиотек ОС.

В образе контейнера для приложения node.js это может быть отображено с помощью трех уровней (начиная с самого верхнего):

  • сценарий app.js и связанные с ним программные компоненты составляют самый верхний уровень;
  • среда выполнения node.js и связанные с ней пакеты образуют следующий уровень;
  • библиотеки ОС образуют нижний уровень.

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

Разделение на уровни позволяет организовать эффективный процесс построения (создания) образов контейнеров. Можно создать образ контейнера с одним уровнем, содержащим все необходимые файлы, но гораздо эффективнее будет разделить программный стек, используемый приложением, на отдельные уровни. Это связано с тем, что приложение и все его зависимости обычно представляют собой отдельные независимые наборы файлов, что описывается в примере на основе приложения node.js.

Образ контейнера может быть создан с использованием другого образа контейнера в качестве основы (или родительского объекта). Поэтому, если снова обратиться к примеру с приложением node.js, первым созданным образом контейнера может быть образ для ОС. Затем можно создать второй образ контейнера для среды выполнения node.js и связанных с ней пакетов, используя образ ОС в качестве родительского объекта. Наконец, третий образ контейнера может быть создан для приложения app.js с использованием в качестве родительского объекта среды выполнения node.js. Родительские образы создают нижние уровни для нового образа, построенного поверх них. Поэтому в этом примере библиотеки ОС становятся самым нижним уровнем, среда выполнения node.js — средним уровнем, а приложение app.js — самым верхним уровнем.

Такая модель организации позволяет каждому образу решать только свои собственные задачи. Например, если среде выполнения node.js не нужны все файлы из библиотек ОС, она может удалить ненужные файлы. Таким образом, при создании образа контейнера основной вопрос заключается в том, какой (какие) базовый(ые) образ(ы) использовать.

Многоуровневая организация файловой системы также применяется и к контейнерам, но с одним отличием. Когда контейнер создается из образа контейнера, формируются те же уровни файловой системы, что и в образе контейнера, но они рассматриваются как доступные только для чтения. Эти уровни называются уровнями образа. Приложение, работающее в контейнере, не может изменять файлы на уровнях образа. Однако поверх уровней, присутствующих в образе контейнера, добавляется дополнительный записываемый уровень — он называется уровнем контейнера (в отдельных контейнерных средах он называется уровнем «песочницы»). Все изменения в файлах, внесенные работающим в контейнере приложением, записываются на уровне контейнера, будь то создание новых файлов, изменение существующих или удаление ненужных файлов. Это подразумевает принцип копирования при записи для файлов в контейнере.

В результате использования уровней образа, предназначенных только для чтения, и принципа копирования при записи уровни образа могут совместно использоваться различными контейнерами. Это позволяет экономить на хранении данных и памяти во время выполнения и сократить время запуска контейнеров [из 7.3.2 Многоуровневая файловая система ГОСТ Р 70860—2023]

7.3.3 Репозитории и реестры образов контейнеров ГОСТ Р 70860—2023

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

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

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

За обеспечение возможности хранения и получения доступа к образам контейнеров отвечает реестр контейнеров. Реестры контейнеров могут предоставляться как общедоступные облачные сервисы или как частные облачные сервисы. Примером общедоступного облачного сервиса для предоставления реестра контейнеров является Docker Hub, доступный по адресу: hub.docker.com. Реестры контейнеров имеют сервисные интерфейсы, которые обеспечивают по крайней мере возможность выполнения операций push и pull. Операция push закачивает один или несколько образов в реестр, а операция pull скачивает один или несколько образов из реестра.

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

Например, репозиторий контейнеров может содержать набор из четырех образов контейнеров с именами some_os_libs:16.01, some_os_libs:16.02, some_os_libs:16.03, some_os_libs:latest. В этом случае в репозитории имеются четыре записи для разных версий ОС, каждая из которых имеет метку номера версии. Версия с меткой «latest» (последняя) указывает на тот же образ контейнера, что и версия с меткой «16.03».

Это объясняется тем, что, если другим образам контейнеров необходимо всегда использовать последнюю версию образа контейнера ОС в качестве родительского элемента, они могут использовать метку «latest» при получении образа, что приведет к автоматическому обновлению, когда новые образы контейнеров более поздних версий ОС будут загружены в реестр контейнеров. Другой областью применения меток, используемых в репозиториях образов, является создание образов для конкретных целевых сред. В качестве альтернативного метода можно использовать образы fat-мэнифестов [из 7.3.3 Репозитории и реестры образов контейнеров ГОСТ Р 70860—2023]