MAATRIX / Блог / Приватный Docker Registry на сервере: частые ошибки и решения

Приватный Docker Registry на сервере: частые ошибки и решения

Приватный Docker Registry на сервере: частые ошибки и решения

MAATRIX

Свой реестр образов подняли, а он встречает ошибками: то «http: server gave HTTP response to HTTPS client», то push обрывается на 413, то login не проходит, то диск внезапно кончился. Эти ошибки приватного Docker Registry на сервере типовые, и почти каждая связана с HTTPS, прокси или авторизацией. Разберём их по схеме «симптом — причина — решение».

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

С чего начинать диагностику реестра

Сначала убедитесь, что сам контейнер реестра жив и отвечает. Проверьте его состояние и обратитесь к служебному эндпоинту напрямую с сервера:

docker ps -a | grep registry
docker logs --tail=50 registry
curl -k https://registry.example.com/v2/

Эндпоинт /v2/ — пульс реестра. При работающей авторизации он вернёт 401, что нормально: значит, реестр жив и требует логин. Пустой ответ {} — реестр открыт без авторизации. Ошибка соединения — проблема в прокси или сети. Отдельно посмотрите, что происходит на стороне клиента при push или pull, потому что многие ошибки видны именно в его выводе:

docker login registry.example.com

Эта команда сразу покажет, доходит ли клиент до реестра, принимается ли сертификат и работает ли авторизация. Держа перед глазами логи реестра, ответ /v2/ и вывод клиента, вы локализуете почти любую проблему. Дальше — разбор частых симптомов.

Ошибка «server gave HTTP response to HTTPS client»

Самая частая и сбивающая с толку ошибка. Docker при push или pull пишет: «http: server gave HTTP response to HTTPS client». Причина в том, что Docker всегда обращается к реестру по HTTPS, а ваш реестр отвечает по HTTP — то есть шифрование не настроено или прокси отдаёт незащищённое соединение.

Правильное решение — настроить перед реестром реверс-прокси с валидным сертификатом Let's Encrypt, чтобы Docker получал честный HTTPS:

certbot --nginx -d registry.example.com

Есть и быстрый, но небезопасный обходной путь для внутренних сетей — объявить реестр «небезопасным» в настройках Docker на клиенте. Так делать на боевом реестре не стоит, но для локальной отладки иногда допустимо:

echo '{ "insecure-registries": ["registry.example.com:5000"] }' > /etc/docker/daemon.json
systemctl restart docker

Настоятельно рекомендуется именно первый путь с настоящим HTTPS. Небезопасный реестр передаёт образы и пароли открыто, и в продакшене это недопустимо. Если сертификат уже есть, а ошибка остаётся, проверьте, что прокси проксирует на реестр и отдаёт наружу именно HTTPS, а не заворачивает всё обратно в HTTP.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Push большого образа обрывается на 413

Симптом: мелкие образы заливаются, а крупный обрывается с ошибкой 413 Request Entity Too Large. Причина не в самом реестре, а в реверс-прокси перед ним: по умолчанию он ограничивает размер тела запроса, и большой слой образа в него не влезает.

Решение — снять ограничение размера в конфиге прокси. Для Nginx это директива в блоке location реестра:

location / {
    proxy_pass http://127.0.0.1:5000;
    client_max_body_size 0;
}

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

nginx -t && systemctl reload nginx

Родственная проблема — таймауты при заливке очень больших образов на медленном канале: push доходит до определённого процента и обрывается. Здесь помогает увеличение таймаутов проксирования. Но если образы стабильно огромные и push идёт минутами, стоит и оптимизировать сами образы (многоступенчатая сборка, меньше слоёв), и убедиться, что у сервера достаточно быстрый диск и канал.

Не проходит авторизация

Симптом: docker login отвергает верный, как вам кажется, пароль, или push возвращает 401 Unauthorized. Причин несколько. Первая — файл htpasswd создан неправильно. Docker Registry требует шифрование bcrypt, и если файл сгенерирован без флага -B, авторизация не сработает. Пересоздайте пользователя правильно:

docker run --rm --entrypoint htpasswd httpd:2 -Bbn deployer 'СильныйПароль' > /opt/registry/auth/htpasswd
docker restart registry

Вторая причина — файл htpasswd не смонтирован в контейнер или переменные окружения авторизации заданы неверно. Проверьте, что при запуске реестра указаны и путь к файлу, и включение htpasswd-режима. Третья, коварная причина — кешированные учётные данные на клиенте: после смены пароля старый логин мог сохраниться. Сбросьте его и войдите заново:

docker logout registry.example.com
docker login registry.example.com

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

Диск переполнен и образы не удаляются

Неприятный сюрприз: реестр перестал принимать push, потому что кончилось место. Образы копятся, а старые версии не исчезают сами. Проверьте, сколько занято:

df -h
du -sh /opt/registry/data

Особенность Docker Registry в том, что удаление тега не освобождает место сразу — данные остаются, пока не запущена сборка мусора. Причём по умолчанию удаление вообще может быть выключено, и тогда теги не удаляются в принципе. Чтобы освобождать место, удаление нужно включить переменной окружения реестра, а затем периодически запускать сборку мусора:

docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

Сборка мусора физически удаляет слои, на которые больше не ссылается ни один тег. Планируйте её регулярно, иначе диск будет только расти. И помните: реестр по своей природе прожорлив к диску — если образов много и они большие, никакая чистка не отменит потребность в объёме. Это прямой повод взять VPS с большим NVMe. У MAATRIX серверы с быстрым и вместительным диском доступны в локациях RU, US и UK с оплатой из России картой или криптой.

Профилактика типовых ошибок

Большинство проблем реестра не возникает при правильной первичной настройке. Всегда ставьте перед реестром реверс-прокси с настоящим HTTPS — это снимает и ошибку HTTP/HTTPS, и передачу паролей открытым текстом. Задавайте client_max_body_size 0, чтобы крупные образы заливались без 413. Создавайте пользователей htpasswd с флагом -B и монтируйте файл авторизации в контейнер. Данные реестра держите в томе и включайте в бэкапы.

Отдельно наладьте гигиену хранилища: включите удаление образов, регулярно запускайте сборку мусора и мониторьте свободное место, чтобы push не встал в самый неподходящий момент. Если реестр обслуживает команду или пайплайны, продумайте политику хранения версий — сколько последних тегов держать, а что удалять. Такой подход держит реестр компактным и предсказуемым. А когда объём образов и трафик перерастают текущий сервер, перенос на более мощный VPS с большим диском решает то, что не решить чисткой, — и делает собственный реестр надёжным элементом инфраструктуры.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Что означает «server gave HTTP response to HTTPS client»?

Docker обращается по HTTPS, а реестр отвечает по HTTP; настройте реверс-прокси с валидным сертификатом Let's Encrypt, а не отключайте безопасность.

Почему push большого образа падает с 413?

Реверс-прокси ограничивает размер тела запроса; задайте client_max_body_size 0 в конфиге Nginx и перезагрузите прокси.

Из-за чего не проходит docker login?

Чаще всего файл htpasswd создан без bcrypt (-B) или не смонтирован; пересоздайте пользователя правильно и сбросьте кешированный логин через docker logout.

Почему удаление тегов не освобождает место?

В реестре нужно включить удаление и периодически запускать сборку мусора garbage-collect; иначе слои остаются на диске.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.