Сообщение об ошибке
http: server gave HTTP response to HTTPS client
Программы добавляют свой префикс: Docker выводит «Error response from daemon: Get \"https://<registry>/v2/\": http: server gave HTTP response to HTTPS client», программы на Go — «Get \"https://…\": http: server gave …». Если ответ не похож и на HTTP, Go сообщает «tls: first record does not look like a TLS handshake».
Go net/http — the TLS handshake received a plain HTTP response (also printed by Docker, Helm, Terraform)
Что это означает
HTTP-клиент Go начал TLS-рукопожатие, а сервер ответил незашифрованным HTTP-ответом; Go распознаёт байты «HTTP/» и сообщает, что сервер работает по HTTP, а не по HTTPS. Самый известный случай — docker pull или docker login к собственному реестру, работающему без TLS: Docker требует HTTPS для любого реестра, который не находится на loopback-адресе и явно не помечен как незащищённый (insecure).
Почему это происходит
Реестр контейнеров без TLS
частоРеестр registry:2 (distribution), Harbor или Nexus, запущенный для тестирования по незашифрованному HTTP. Docker, containerd, Podman, Helm и Skopeo ожидают HTTPS для всего, кроме localhost.
https:// с портом HTTP
частоURL или конфигурация, где https:// сочетается с портом 80, 8080 или внутренним портом сервиса.
TLS терминируется на прокси, который слушает другой порт
иногдаБэкенд за балансировщиком нагрузки работает по HTTP; клиенты, которые обходят балансировщик и обращаются к порту бэкенда по https://, получают эту ошибку.
Как исправить
- 1.
Убедитесь, что порт работает по незашифрованному HTTP
Это подтверждает строка состояния HTTP в ответ на запрос по http://. Используйте TLS-эндпоинт (или http://, где это допустимо).
bash curl -si http://registry.example.com:5000/v2/ | head -1 # answers over plain HTTP? - 2.
Переведите реестр на TLS
Выпустите для реестра сертификат (через публичный ACME или у CA компании) и настройте его либо поставьте перед реестром прокси, который терминирует TLS.
yaml # Docker registry (distribution) config.yml: serve TLS http: addr: :5000 tls: certificate: /certs/registry.example.com.fullchain.pem key: /certs/registry.example.com.key - 3.
Крайняя мера: пометьте реестр как незащищённый (daemon.json)
Если указать реестр в insecure-registries в /etc/docker/daemon.json (и перезапустить dockerd), Docker будет обращаться к нему по незашифрованному HTTP. Образы и учётные данные тогда передаются без шифрования и без аутентификации; используйте это только в изолированных лабораторных сетях.
json { "insecure-registries": ["registry.example.com:5000"] }