Home » Уклонитесь от следующего Dockerpocalypse: как стать владельцем собственного адреса Docker Registry

Уклонитесь от следующего Dockerpocalypse: как стать владельцем собственного адреса Docker Registry

Как вы, возможно, заметили, на этой неделе Docker Hub резко изменил политику и фактически уведомил о выселении за 30 дней почти все образы, управляемые сообществом.

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

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

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

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

Трудная часть заключается в том, что делать вместо этого.

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

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

Что, если бы вы могли использовать свой собственный фиксированный URL-адрес реестра, в своем собственном домене и полностью под вашим контролем, но без необходимости самостоятельного размещения навсегда или даже фиксации в каком-либо конкретном реестре или покрытия всех расходов на пропускную способность и хранение?

Мы ищем способ:

  • Ссылайтесь на свои изображения с адреса, которым вы полностью управляете (docker pull docker.my-org.example.com/org/my-image)
  • Сделайте это, сохраняя при этом возможность использовать любой реестр, размещенный в другом месте, или самостоятельно размещенный.
  • Избегайте хранения, загрузки или предоставления контента отдельно. По крайней мере, на данный момент есть довольно много других реестров, которые с радостью сделают это для общедоступных изображений бесплатно, и даже если бы их не было, мы хотели бы избежать дополнительных задержек или платы за вход и выход из-за проксирования этого трафика.
  • Возможность изменить резервный реестр, который мы будем использовать в будущем, без повторного изменения каких-либо адресов образов..
Read more:  Маркос сталкивается с филиппинским ростом, инвестиционные тесты на второй год

Что, если я скажу вам, что это на самом деле очень просто?

Изучение возможностей

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

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

Классическое решение «хост в собственном домене» — использовать CNAME на уровне DNS. Это означает настройку DNS-записи в вашем домене, которая указывает на домен в другом месте, эффективно определяя псевдоним. Когда клиент пытается подключиться, он будет искать your-registry.example.comнайдите запись, ссылающуюся на вспомогательный реестр (registry.hub.docker.com), и тогда все запросы будут отправляться туда.

Если бы это работало здесь, это было бы здорово! Нулевой хостинг не требуется, просто обработайте его на уровне DNS.

К сожалению, для этого требуется, чтобы целевой сервер правильно обрабатывал HTTP-запросы с вашим сторонним доменным именем в Host заголовок, зная, что они должны обрабатываться как запросы к реальному сервису. По крайней мере, для Docker Hub это невозможно (конечно, не бесплатно — хотя, как и многие другие сервисы, это может предлагаться в качестве платного дополнения). Запросы, отправленные в Docker Hub с неправильным именем хоста, просто терпят неудачу:

> curl -I 
HTTP/1.1 200 OK
...

> curl -I -H'Host: example.com' 
HTTP/1.0 503 Service Unavailable
...

Я подозреваю, что это относится и ко многим другим реестрам, поэтому перенаправление только на уровне DNS отсутствует.

Следующий план: можем ли мы сделать это с помощью перенаправления и/или проксирования на уровне HTTP? В самом HTTP есть множество стандартных инструментов и подходов для этого, а также целая экосистема обратных прокси. Однако, к сожалению, не гарантируется, будут ли клиенты API обрабатывать перенаправления так, как нам хотелось бы, а проксирование, не сталкиваясь с другими проблемами, нетривиально.

Чтобы выяснить, сработает ли это, нам нужно покопаться в трафике Docker напрямую.

Как работает Docker Pull

Во-первых, давайте посмотрим, что на самом деле делает Docker pull под капотом.

Когда вы бежите docker pullили сделать что-нибудь еще с Docker (например, создать образ), который запускает получение образа в пути, есть несколько запросов, которые должны произойти, чтобы загрузить полный образ, который вы ищете.

Чтобы разобраться в этом трафике, проще всего использовать инструмент отладки HTTP (например, HTTP-инструментарий), чтобы просмотреть необработанные взаимодействия, и настроить Docker для использования его в качестве HTTP-прокси (документы здесь) и доверять сертификату ЦС (здесь).

Read more:  200+ гендерно-нейтральных детских имен, от Адриана до Сиона

Если вы не очень увлечены этим, вы все можете пропустить это — я проделал за вас тяжелую работу. Вот что происходит, когда вы бежите docker pull nginx:


HTTP Toolkit, показывающий список запросов, отправленных во время извлечения Docker

Что мы имеем здесь:

  • инициал /v2/ запрос на проверку статуса API (документы здесь). В Docker Hub это обычно возвращает 401 с заголовками, перенаправляющими клиента для аутентификации.
  • Запрос аутентификации на auth.docker.ioкоторый возвращает JWT.
  • Запрос HEAD к URL-адресу базового изображения (/v2/library/nginx/manifests/latest), который возвращает ответ с docker-content-digest заголовок, содержащий хэш sha256:


    Заголовки ответа запроса дайджеста

  • Два запроса GET для определенных манифестов, оба получили 200:

    • /v2/library/nginx/manifests/sha256:aa0a... (хэш из предыдущего заголовка ответа), который возвращает список манифестов, помеченных платформой:


      Содержимое манифеста в формате JSON со списком хэшей для каждой платформы.

    • /v2/library/nginx/manifests/sha256:942a... (хэш платформы linux из предыдущего запроса), который возвращает хэши списка манифеста для отдельных слоев изображения.


      Содержимое манифеста JSON со списком хэшей для каждого слоя

  • Набор параллельных запросов для определенных хэшей больших двоичных объектов, все в формате
    /v2/library/nginx/blobs/sha256:$HASH.

    Каждый из них делает нет вернуть контент – они возвращают 307 редиректов на контент! В случае с Docker Hub они возвращают перенаправления на CDN с поддержкой Cloudflare:


    Ответ перенаправления 307 с заголовком Location, указывающим на production.cloudflare.docker.com.

  • Чередующийся набор параллельных запросов к хосту реального изображения (production.cloudflare.docker.com), чтобы фактически получить содержимое конфигурации и слоев изображения.

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

Прозрачная обертка реестра Docker

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

Удобно, что в трафике выше мы видим, что редиректы уже есть, и работают! Это означает, что все клиенты Docker должен поддержка редиректов по крайней мере для /blobs/ запросы (иначе Docker Hub был бы непригоден для использования) и поэтому, вероятно, поддерживает их для всех запросов.

Итак, учитывая это, что произойдет, если мы просто сделаем то же самое непосредственно сами, создав правило для возврата 307 HTTP-перенаправлений со всех $OUR_HOST/* URL-адреса соответствующих $OUR_REGISTRY/* на любой запрос?


Серия запросов, каждый из которых получает перенаправление 203 на Docker Hub, а затем успешный ответ там

Бинго.

Это работает достаточно хорошо! Мы добавляем немного накладных расходов с дополнительным ответом перенаправления 307 на каждом шаге (каждый запрос с красным значком представляет собой введенное перенаправление), но они очень быстрые, все здесь отправляется успешно и отлично работает в каждом сценарии. Я тестировал. Определенно достаточно хорошо для начала (и, поскольку все это будет под нашим собственным контролем, мы можем итерировать, чтобы улучшить это решение в будущем).

Я протестировал это с помощью правила быстрой хакерской перезаписи в HTTP Toolkit — как вы делаете это в рабочей среде?

Оказывается, это тоже довольно просто: я создал крошечный контейнер Docker на основе Caddy (мне понравилась ирония публикации этого в Docker Hub), который вы можете развернуть непосредственно на любой платформе хостинга Docker, чтобы сделать это в кратчайшие сроки, или если вы у вас уже есть CDN или хостинговая платформа (например, Netlify), которая позволяет вам определять простые правила, такие как «перенаправить все запросы для X на один и тот же путь на хосте Y», тогда вы тоже можете использовать это.

В моем случае я использую Bunny CDN, у которого есть хорошая система правил, которая может сделать это очень легко, например:


Пограничное правило Bunny.net, перенаправляющее весь трафик на register.hub.docker.com%{Request.Path}

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

Если вы хотите ограничить подобные запросы самостоятельно с помощью других инструментов, вам просто нужно убедиться, что запросы ко всем путям URL, начинающимся с /v2/$YOUR_ORG/ перенаправляются вместе с конкретными /v2/ конечная точка – без этой последней аутентификация конечной точки не будет работать.

Как только это на месте, у вас все хорошо. В моем случае я развернул это как docker.httptoolkit.techтак что теперь вы можете получить мои образы Docker с этого имени хоста, даже если они в настоящее время все еще размещены в Docker Hub, например:

> docker pull docker.httptoolkit.tech/httptoolkit/docker-socks-tunnel

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

Уклонение от следующего Dockerpocalypse

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

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

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

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.