Mensagem de erro
http: server gave HTTP response to HTTPS client
Cada programa acrescenta o próprio prefixo: o Docker imprime “Error response from daemon: Get \"https://<registry>/v2/\": http: server gave HTTP response to HTTPS client”, e programas em Go, “Get \"https://…\": http: server gave …”. Quando a resposta também não é HTTP, o Go diz “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)
O que significa
O cliente HTTP do Go iniciou um handshake TLS, e o servidor devolveu uma resposta HTTP não criptografada; o Go reconhece os bytes “HTTP/” e informa que o servidor fala HTTP, e não HTTPS. O caso mais conhecido é o docker pull ou o docker login em um registro auto-hospedado que roda sem TLS: o Docker exige HTTPS de todo registro que não esteja em um endereço de loopback nem tenha sido marcado explicitamente como inseguro.
Por que acontece
Um registro de contêineres sem TLS
comumUm registry:2 (distribution), Harbor ou Nexus iniciado em HTTP não criptografado para testes. Docker, containerd, Podman, Helm e Skopeo esperam HTTPS para tudo o que não seja localhost.
https:// com a porta HTTP
comumUma URL ou configuração que combina https:// com a porta 80, a 8080 ou a porta de um serviço interno.
Um proxy em outra porta faz a terminação do TLS
ocasionalO backend fala HTTP atrás de um balanceador de carga; clientes que contornam o balanceador e acessam a porta do backend com https:// recebem este erro.
Como corrigir
- 1.
Confirmar que a porta fala HTTP não criptografado
Uma linha de status HTTP em resposta a http:// confirma isso. Use o endpoint TLS (ou http://, onde isso for aceitável).
bash curl -si http://registry.example.com:5000/v2/ | head -1 # answers over plain HTTP? - 2.
Servir o registro via TLS
Dê ao registro um certificado (de ACME público ou da CA da empresa) e configure-o, ou coloque na frente dele um proxy que faça a terminação do 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.
Último recurso: marcar o registro como inseguro (daemon.json)
Listar o registro em insecure-registries no /etc/docker/daemon.json (e reiniciar o dockerd) permite que o Docker se comunique com ele em HTTP não criptografado. Imagens e credenciais passam então a trafegar sem criptografia e sem autenticação; use isso só em redes de laboratório isoladas.
json { "insecure-registries": ["registry.example.com:5000"] }