本文へスキップ
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/」のバイト列を認識し、サーバーが HTTPS ではなく HTTP で通信していると報告します。最もよく知られているのは、TLS なしで動いているセルフホストのレジストリに対する docker pull や docker login です。Docker は、ループバックアドレス上にあるか、明示的に insecure と指定されたレジストリを除き、すべてのレジストリに 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.

    最後の手段:レジストリを insecure に指定する(daemon.json)

    /etc/docker/daemon.json の insecure-registries にレジストリを記載して dockerd を再起動すると、Docker はそのレジストリと平文の HTTP で通信できるようになります。その場合、イメージと認証情報は暗号化も認証もされずに送られます。隔離された検証用ネットワークでのみ使ってください。

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

関連するエラー

署名エラーデータベースをすべて見る