跳到主要内容
ecdsa.com
Go net/httpGo

错误信息

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)

含义

Go 的 HTTP 客户端发起了 TLS 握手,服务器却用明文 HTTP 响应作答;Go 识别出“HTTP/”字节,于是报告服务器使用的是 HTTP 而不是 HTTPS。最常见的情况是对未启用 TLS 的自托管镜像仓库执行 docker pull 或 docker login:对于不在环回地址上、也没有被显式标记为不安全的镜像仓库,Docker 一律要求使用 HTTPS。

原因

修复方法

  1. 1.

    确认该端口使用明文 HTTP

    如果用 http:// 访问时返回了 HTTP 状态行,就可以确认。改用 TLS 端点(或者在可以接受的场合使用 http://)。

    bash
    curl -si http://registry.example.com:5000/v2/ | head -1   # answers over plain HTTP?
  2. 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. 3.

    最后手段:把镜像仓库标记为不安全(daemon.json)

    把该镜像仓库列入 /etc/docker/daemon.json 的 insecure-registries 中(并重启 dockerd),Docker 就会用明文 HTTP 与它通信。此后镜像和凭证的传输既不加密,也不经过身份验证;只在隔离的实验网络中使用。

    json
    {
      "insecure-registries": ["registry.example.com:5000"]
    }

相关错误

浏览完整的签名错误库