Рубрики
Uncategorized

Как мы сократили время толкания Docker на 90%

В Kelda мы строим Blimp, версию Docker Compose, которая работает в облаке. Наша цель — ИМП … Tagged с Docker, DevOps, Microservices.

В Kelda мы строим Blimp, версию Docker Compose, которая работает в облаке. Наша цель состоит в том, чтобы повысить производительность разработки, предоставив разработчикам альтернативу увязанности их локальных систем множеством контейнеров Docker, жаждущих ресурсов.

Мы приложили много инженерных усилий, чтобы поддержать все поля Docker Compose, обычно используемые во время локальной разработки, такие как тома , порты и сборка Анкет В этом посте я немного расскажу о том, что мы получили от опыта, поскольку это связано с Docker Compose’s сборка функциональность.

services:
    service:
        build: .

Когда у сервиса есть сборка Field, Blimp строит ваши изображения локально и подталкивает их к облаку, чтобы их можно было извлечь в среду разработки. Этот толчок может быть разочаровывающим медленным, особенно в домашних сетях. Ожидание 30 минут для загрузки изображения, прежде чем начать развиваться, было просто неприемлемо для нас.

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

В этом посте я расскажу:

  • Что именно происходит, когда вы делаете Docker push
  • Как мы использовали это, чтобы создать нашу функцию предварительного толчка и уменьшить время толчки изображения на 90%.

Изображения — это слои

Прежде чем погрузиться в API Push, вам сначала нужно понять, что такое изображение Docker.

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

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

Например, в следующем, От Python говорит Docker заложить основу нашего изображения с существующими слоями Python. Точно так же Копия Анкет Создает новый слой, который содержит все файлы в Анкет (то есть текущий рабочий каталог, который называется контекстом

FROM python
COPY . .
CMD python app.py

Базовое изображение Python — 934MB Анкет Предполагая, что пользователь копирует в 2 МБ файлов, базовое изображение будет составлять 99% полученного изображения!

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

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

Возвращая его к примеру Python выше, мы хотим сделать так, чтобы Python Слои не загружаются по сети пользователя. Вместо этого наши серверы будут «предварительно подталкивать» слои с наших серверов с высокой пропускной способностью. Тогда пользователь Docker push Просто нужно подтолкнуть слой для Копия Анкет .

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

Но нам все еще приходилось разработать способ предварительного пропадения базовых слоев изображения в реестре, чтобы Docker Push API повторно использовал их.

Docker Push API

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

Простое кэширование слоя

Каждая загрузка слоя начинается с Голова Запросите, чтобы проверить, существует ли слой в реестре.

Если уровень уже существует в реестре, то реестр отвечает 200 ОК Ответ, и клиент Docker не беспокоит его снова. В этих ситуациях Docker push показывает следующий выход:

6b73f8ddd865: Layer already exists

Если слой не существует, тогда реестр отвечает 202 Принято вместе с URL -адресом, который следует использовать для загрузки слоя. Затем клиент загружает изображение в куски через ПЛАСТЫРЬ запросы или непосредственно через один Положить запрос.

Эта проверка слоя работает только тогда, когда рассматриваемые слои существуют в том же репозитории, что и изображение, которое нажимается. Так БПИПП/БАКЕНД: 1 и БПИП/БАКЕНД: 2 может поделиться слоями, но БПИПП/БАКЕНД: 1 Не могу делиться слоями с БИЛЬМ/Еще одно изображение: 1 (Не используя другой API, который я сейчас опишу).

Крестные репозитории

Возможно, вы видели следующий выход при запуске Docker push до. Этот выход означает, что толчок использует Крестные репозитории Mounts , что является классной особенностью для кэширования слоев по всему несколько картинки.

e1c75a5e0bfa: Mounted from library/ubuntu

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

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

Оптимизация дирижабля

Если вы используете пользовательское изображение Docker для разработки, Blimp автоматически строит и нажимает изображение при запуске песочницы. Изображение для каждой службы подталкивается к blimp-registry.kelda.io//: где есть уникальный идентификатор для вашей песочницы, и это хэш, чтобы убедиться, что мы всегда запускаем последнюю версию вашего изображения.

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

Первоначальный дизайн

Сначала мы хотели использовать Крестные репозитории Mounts Анкет Это позволило бы всем нашим пользователям поделиться одними и теми же базовыми изображениями, поэтому нам пришлось бы только нажать базовое изображение для очень первый пользователь это ссылается на это. Кроме того, это заставило нас создать частные кэши изображения для команд, чтобы они могли поделиться слоями со своих Dockerfile, кроме базового изображения.

Мы надеялись сделать что -то вроде этого:

  1. Проанализируйте изображение Dockerfile, чтобы выяснить, каково его базовое изображение.
  2. Отправьте запрос нашему серверу, чтобы подтолкнуть это базовое изображение в реестр с именем blimp-registry.kelda.io/public/: Анкет
  3. Отметьте базовое изображение локально с помощью blimp-registry.kelda.io/public/: Так что Docker предоставил бы его как крепление репозитория.
  4. Нажмите изображение Docker push Анкет

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

Мы подумали о том, чтобы предоставить пользователям доступ к общественному репо, но мы считали это слишком небезопасным. Мы также считали отказаться Docker push полностью в пользу Go-ContainerRegistry , но это повлекло за собой внесение значительных изменений в Go-ContainerRegistry Чтобы показать обновления Push Push.

Итак, мы вернулись на чертежную доску.

Пересмотренный дизайн

Отказавшись от приколов репозитория Cross, мы спросили: зачем беспокоиться о прикреплениях репозитория, когда мы могли бы просто подтолкнуть непосредственно к репозиторию пользователя?

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

В конечном счете, это то, на чем мы остановились. Репозиторий для каждой службы ( blimp-registry.kelda.io// ) всегда имеет основание Обвяжите, что наши серверы нажимают на базовое изображение. Затем реестр автоматически ссылается на него во время обычного API, изложенного выше, когда пользователь выжимает свое изображение — никаких непристойных манипуляций с состоянием Докера не требуется.

Собрать все это вместе, это то, что происходит, когда Blimp нажимает на локально построенное изображение:

  1. Blimp Cli анализирует ссылку на базовое изображение из Dockerfile изображения.
  2. CLI Blimp сообщает серверам рисков, чтобы подтолкнуть базовое изображение к blimp-registry.kelda.io//:base Анкет
  3. Blimp CLI создает изображение, используя то же базовое изображение.
  4. Blimp CLI подталкивает полное изображение к blimp-registry.kelda.io//: Анкет
  5. Докер проходит через слои один за другим и толкает их. Если слой из базового изображения, реестр замечает и инструктирует CLI пропустить толчок.
  6. Для слоев, не в базовом изображении, Docker выполняет полный процесс загрузки.

Вывод

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

Рекомендации

Посмотрите, как быстро это сами! Попробуйте пример

Узнайте больше о Docker Internals — Посмотрите, как хранятся учетные данные реестра.

Прочитайте спецификацию для API Docker Push

По: Кристофер Купер

Оригинал: «https://dev.to/ethanjjackson/how-we-cut-our-docker-push-time-by-90-4o69»