Closed luckylinux closed 5 months ago
As far as I know there is no communication between two containers. The registry just adds realm
to the Www-Authenticate
header. The client (curl
, docker login
) is just using that to authenticate.
# curl --head -sSL http://127.0.1.1:5000/v2/;
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Docker-Distribution-Api-Version: registry/2.0
Www-Authenticate: Bearer realm="http://127.0.1.1:5001/auth",service="Docker Registry"
Date: Thu, 25 Apr 2024 11:43:56 GMT
Content-Length: 87
As far as I know there is no communication between two containers. The registry just adds
realm
to theWww-Authenticate
header. The client (curl
,docker login
) is just using that to authenticate.# curl --head -sSL http://127.0.1.1:5000/v2/; HTTP/1.1 401 Unauthorized Content-Type: application/json; charset=utf-8 Docker-Distribution-Api-Version: registry/2.0 Www-Authenticate: Bearer realm="http://127.0.1.1:5001/auth",service="Docker Registry" Date: Thu, 25 Apr 2024 11:43:56 GMT Content-Length: 87
Weird ... Nothing seemed to be happening in my case. Right now I had to fall back to NO AUTH at all because it just didn't work.
But maybe I'm pointing at the wrong "registry" when I try pulls ? Should I point (e.g. docker pull
) to the Registry itself or the Authentication Container ? I thought it should be the Registry itself (as usual), but maybe I got that wrong.
I would start with curl
. And if that seems alright use can do a docker login 127.0.1.1:5000
. And if that works a docker pull 127.0.1.1:5000/foo/bar
.
So I made some progress.
One issue is that I had
realm: "https://127.0.0.1:5001/auth"
Whereas I'm using Traefik Proxy, so I should have been using just the Internal Hostname AND without TLS/HTTPS:
realm: "http://docker-local-mirror-auth:5001/auth"
However, it still fails in the end.
It seems that the HOST System wants to Contact docker-local-mirror-auth
directly, when issueing podman login docker.MYDOMAIN.TLD
.
I thought the communication would have been like this: HOST -> Docker Local Registry [ --> INTERNAL COMMUNICATION --> ] Docker Auth
But maybe I need to expose also the Docker Auth Service over TLS (via Traefik) on a publicly accessible Hostname (just I did for the "main" Registry at docker.MYDOMAIN.TLD
) ?
Yup, that's correct. This doesn't communicate with the registry at all. The client will be directed from the registry to the with server, then with server will do the auth process and return a token, and finally the client will use that token and provide it to the registry. As for the realm, it needs to be accessible by the client as that is what the client is told to fetch the token from
And if I setup another Traefik Configuration for the new subdomain I createed, I get this:
Error: authenticating creds for "docker.MYDOMAIN.TLD": Requesting bearer token: invalid status code from registry 504 (Gateway Timeout)
Whereas now I am getting this, but I don't think I changed anything:
Error: authenticating creds for "docker.MYDOMAIN.TLD": Requesting bearer token: invalid status code from registry 400 (Bad Request)
Again absolutely nothing in the Auth Container Logs besides the normal Startup.
As for the Docker Registry Container, it's filled with completely useless logs.
Is it a case of the Proxy needing to setup some X-Forwarded-to
headers etc ?
Or having to enable autoredirect in the Registry Configuration ?
EDIT 1: this could be related to the fact that I'm trying to do podman login
from the HOST where the Containers are running.
Traefik logs show a bit more self-explanatory message, since the Traefik TLS Certificate is valid for *.MYDOMAIN.TLD
, not localhost
:
time="2024-05-05T19:59:03Z" level=debug msg="Serving default certificate for request: \"localhost\""
time="2024-05-05T19:59:03Z" level=debug msg="http: TLS handshake error from 10.89.0.38:54112: remote error: tls: bad certificate"
EDIT 2: actually I am getting that TLS warning with all Connections, weird. I can access the Traefik Dashboard without Issues though (valid LetsEncrypt Certificate) ...
I could successfully login now (on the HOST where the Containers are running) by DISABLING TLS in docker_auth
Container according to https://github.com/cesanta/docker_auth/blob/main/examples/non_tls.yml
(basically moving Certificates & Key from the server
section to the token
Section)
In Docker Registry Container Configuration I still have HTTPS going through Traefik:
realm: "https://docker-auth.MYDOMAIN.TLD/auth"
And in Compose File I had added the following in the middlewares section of registry
(unsure if this had any effect at all though). Full compose.yml
file for reference:
version: "3.8"
services:
docker-local-mirror-registry:
image: registry:latest
pull_policy: "missing"
container_name: docker-local-mirror-registry
restart: "unless-stopped"
volumes:
- ~/containers/data/docker-local-mirror-registry:/var/lib/registry
- ~/containers/certificates/docker-local-mirror-auth/cert.pem:/cert/auth/cert.pem:ro
- ~/containers/config/docker-local-mirror-registry/registry:/etc/docker/registry:ro
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.docker-local-mirror-registry-router.rule=Host(`docker.MYDOMAIN.TLD`)"
# Headers Middleware
- "traefik.http.routers.docker-local-mirror-registry-router.middlewares=docker-local-mirror-registry-headers,docker-local-mirror-registry-forwardauth"
- "traefik.http.middlewares.docker-local-mirror-registry-headers.headers.customrequestheaders.Connection=Upgrade"
- "traefik.http.middlewares.docker-local-mirror-registry-forwardauth.forwardauth.address=https://docker-auth.MYDOMAIN.TLD/auth"
- "traefik.http.middlewares.docker-local-mirror-registry-forwardauth.forwardauth.trustforwardheader=true"
- "traefik.http.middlewares.docker-local-mirror-registry-forwardauth.forwardauth.authresponseheaders=X-Forwarded-User"
# Setup Service
- "traefik.http.services.docker-local-mirror-registry-service.loadbalancer.server.port=5000"
- "traefik.docker.network=traefik"
environment:
- "REGISTRY_HTTP_ADDR=0.0.0.0:5000"
- "REGISTRY_LOG_LEVEL=debug"
- "REGISTRY_STORAGE_DELETE_ENABLED=false"
- "REGISTRY_STORAGE_DELETE_AGE=1344"
- "REGISTRY_HTTP_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
docker-local-mirror-auth:
image: cesanta/docker_auth:latest
pull_policy: "missing"
container_name: docker-local-mirror-auth
volumes:
- ~/containers/log/docker-local-mirror-auth:/logs
- ~/containers/config/docker-local-mirror-auth:/config:ro
- ~/containers/certificates/docker-local-mirror-auth:/cert/auth:ro
restart: "unless-stopped"
command: --v=2 --alsologtostderr /config/config.yml
networks:
- traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.docker-local-mirror-auth-router.rule=Host(`docker-auth.MYDOMAIN.TLD`)"
# Headers Middleware
- "traefik.http.routers.docker-local-mirror-auth-router.middlewares=docker-local-mirror-auth-headers"
- "traefik.http.middlewares.docker-local-mirror-auth-headers.headers.customrequestheaders.Connection=Upgrade"
# Setup Service
- "traefik.http.services.docker-local-mirror-auth-service.loadbalancer.server.port=5001"
networks:
traefik:
external: true
And finally also the logs of docker-local-mirror-auth
show that indeed some Authentication is taking place.
Finally it seems to be working now :+1:.
EDIT 1: Unauthenticated Pulls seems to be working correctly, but I cannot view the Catalog via the web Browser (JSON) anymore. Is this normal ?
EDIT 2: Fixed link (the correct one to use BEHIND Traefix Proxy is https://github.com/cesanta/docker_auth/blob/main/examples/non_tls.yml)
Glad to hear. I'll close this now :) if you have any other problems, feel free to open a new issue.
@techknowlogick Maybe consider making a "Traefik Example" (or for other Proxies: Caddy etc) available as well. To be honest it was a major Headache for me to get it working (mostly to not correctly understand the principle that BOTH the Registry and the Auth system needs to be accessible externally by the Client that wants to authenticate).
Once the Host/Domain external accessibility was fixed, I was getting an Error: "Client sent an HTTP request to an HTTPS server."
Found this on StackOverflow: https://stackoverflow.com/questions/77890357/i-got-the-error-client-sent-an-http-request-to-an-https-server-even-the-url-i
After that, I turned OFF TLS as explained above for the Auth Container (TLS is provided by Traefik anyways), then it started working :+1:.
I know there are like 300 combinations possible between Auth backend and Proxy etc, but a folder "traefik" for instance with the Compose file & the non-tls example would go a long way in my View ...
I am trying to get this to work with
podman
.I started off with: https://github.com/cesanta/docker_auth/blob/main/examples/simple.yml
This also gave some ideas on how to enable anonymous pulls: https://stackoverflow.com/questions/38310906/anonymous-pull-on-docker-repo-in-artifactory
My Compose File for a Registry running behind Traefik Proxy:
My Registry Configuration:
My Auth Configuration (
docker_auth
):I tried both to access the auth server from
localhost
,127.0.0.1
ordocker-local-mirror-auth
. In theory (which is working at least for PostgreSQL communications with another Container on the same Host),docker-local-mirror-auth
is the one that should be used.No matter what I do, it seems that the Registry never even attemps to contact the Authentication Server. There are no logs on attempted Connection between them. Only an Authorisation Error on the Registry Container ....
Authentication Server Verbose Logs:
Registry Server Debug Logs:
Surely I'm missing something very simple in the config ...
It does NOT seem like a Network Error at least. The Registry doesn't even try to contact the Authentication server. There is no trace of that.