Skip to content
Latchkey

Docker "http: server gave HTTP response to HTTPS client" - Insecure Registry

The Docker daemon tried to talk to the registry over HTTPS, but the registry answered with plain HTTP. The daemon assumes TLS by default, so it refuses the mismatched response.

What this error means

A docker push/pull to a local or self-hosted registry (often on :5000) fails with http: server gave HTTP response to HTTPS client. It is deterministic for that registry until the daemon is told the host serves HTTP.

docker push/pull output
Error response from daemon: Get "https://registry.local:5000/v2/":
http: server gave HTTP response to HTTPS client

Diagnose it: separate auth from naming from rate limits

Registry errors look alike and have unrelated causes. Work out which of the three you have before changing credentials, because a malformed image reference produces an error that reads like an authentication failure.

Terminal
# 1. is the reference even valid? (lowercase, no spaces, valid tag)
docker image inspect "$IMAGE" 2>&1 | head -2

# 2. are you authenticated to the right registry?
cat ~/.docker/config.json | grep -o '"[^"]*\.[^"]*"' | head

# 3. are you rate limited? (Docker Hub anonymous pulls)
curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimit-preview/test:pull" \
  | grep -o '"token"' >/dev/null && echo "token ok"

Common causes

The registry serves plain HTTP, not HTTPS

A development or internal registry without TLS answers over HTTP. The daemon defaults to HTTPS for every registry, so the HTTP response looks wrong.

The registry is not listed as insecure

Until the host is in insecure-registries, the daemon will not fall back to HTTP for it, so every request is attempted over TLS and fails.

How to fix it

Declare the registry insecure (HTTP) in the daemon

Add the host to insecure-registries in daemon.json, then restart Docker. Suitable for CI/dev registries on a trusted network.

daemon.json
# /etc/docker/daemon.json
{ "insecure-registries": ["registry.local:5000"] }

sudo systemctl restart docker

Prefer enabling TLS on the registry

  1. Front the registry with a certificate (a private CA or public cert) and use HTTPS.
  2. If you must use HTTP, restrict it to an isolated CI network.
  3. Keep the insecure-registries list minimal and explicit.

Authenticate in the job, not in the image

.github/workflows/ci.yml
- uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

# GHCR needs this on the job or the push is rejected as unauthorised
permissions:
  contents: read
  packages: write

How to prevent it

  • Serve registries over HTTPS wherever possible.
  • Scope insecure-registries to specific internal hosts only.
  • Document the insecure-registry requirement next to the CI registry config.

Frequently asked questions

What causes Docker "http: server gave HTTP response to HTTPS client"?
There are 2 common causes: the registry serves plain http, not https and the registry is not listed as insecure. A development or internal registry without TLS answers over HTTP.
How do I fix Docker "http: server gave HTTP response to HTTPS client"?
There are 2 fixes depending on which cause you have: declare the registry insecure (http) in the daemon and prefer enabling tls on the registry. Work through them in order, since the first is the most common.
What does Docker "http: server gave HTTP response to HTTPS client" actually mean?
A docker push/pull to a local or self-hosted registry (often on :5000) fails with http: server gave HTTP response to HTTPS client.
How do I stop Docker "http: server gave HTTP response to HTTPS client" happening again?
Serve registries over HTTPS wherever possible. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

This is a registry failure, not a bug in your code. Latchkey detects, repairs, and retries it for you. Start free → 30-day trial · No credit card