A registry that other machines reach needs TLS, so traffic cannot be read or altered, and authentication, so not everyone can push. Distribution takes a certificate and key, and an htpasswd file of bcrypt hashes, through environment variables; a self-signed certificate is enough to try it:
mkdir -p certs auth
openssl req -x509 -newkey rsa:2048 -nodes -days 30 -subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1" \
-keyout certs/reg.key -out certs/reg.crt 2>/dev/null
htpasswd -Bbn booknest 'reg-pass-2026' > auth/htpasswd
docker run -d --name l3-registry-secure -p 127.0.0.1:33543:5000 \
-v "$PWD/certs:/certs:ro" -v "$PWD/auth:/auth:ro" \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/reg.crt -e REGISTRY_HTTP_TLS_KEY=/certs/reg.key \
-e REGISTRY_AUTH=htpasswd -e REGISTRY_AUTH_HTPASSWD_REALM=BookNest \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry:3 >/dev/null; sleep 2
for opts in "" "--cacert certs/reg.crt" "--cacert certs/reg.crt -u booknest:reg-pass-2026"; do
curl -s -o /dev/null -w '%{http_code} ' $opts https://localhost:33543/v2/; done; echo
export DOCKER_CONFIG=$PWD/dockercfg
echo 'reg-pass-2026' | docker login localhost:33543 -u booknest --password-stdin 2>&1 \
| grep -E 'WARNING|Succeeded' | sed "s#$PWD#.#"
docker tag l3-booknest-api:latest localhost:33543/booknest-api:1.3
docker push localhost:33543/booknest-api:1.3 | tail -1; docker logout localhost:33543Output
000 401 200 WARNING! Your credentials are stored unencrypted in './dockercfg/config.json'. Login Succeeded 1.3: digest: sha256:ff7c8911a5d4400d55c18dde397d92d8095f5e3cac3ecc99f7f9a1c9f2ac1f8d size: 856 Removing login credentials for localhost:33543
000 is curl 3,008 rejecting the unknown certificate, 401 the registry rejecting an anonymous client, and 200 a trusted, authenticated one. DOCKER_CONFIG kept this login out of the main client configuration, and the warning shows why a credential helper matters. For a registry on another host, Docker 514 trusts a private CA placed in /etc/docker/certs.d/<host>:<port>/ca.crt.