I am trying to deploy a private docker registry on my server. The Docker registry works if I expose port 5000 via Docker. My goal, however, is to hide it behind traefik. I am using Let's Encrypt certificates.
When I try to access the registry via its traefik subdomain, I get the following error from the registry: remote error: tls: bad certificate
docker_registry | 2022/03/09 15:03:33 http: TLS handshake error from xxx.xxx.xxx.xxx:48544: remote error: tls: bad certificate
After some Googling I think the reason might be that traefik terminates TLS, but that the registry expects TLS to be present. I am unsure though. Do you know why this might be happening and how I can make it work?
Works:
docker login registry.domain.com:5000
Does not work: (but should ideally work)
docker login registry.domain.com
My traefik and registry setup is following here:
Summary
Traefik Setup:
docker-compose.yml
.env only contains the DASHBOARD_PASSWORD used in dyanmic_conf.yml.
version: '2'
services:
traefik:
image: traefik:2.6
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.yml:/traefik.yml
- ./dynamic_conf.yml:/dynamic_conf.yml
- ./acme.json:/acme.json
networks:
- traefik
env_file: .env
networks:
traefik:
external: true
traefik.yml
entryPoints:
dashboard:
address: :8080
http:
address: :80
https:
address: :443
api:
dashboard: true
certificatesResolvers:
myhttpchallenge:
acme:
httpChallenge:
entryPoint: http
email: my@mail.com
storage: acme.json
providers:
docker:
exposedByDefault: false
network: traefik
file:
filename: dynamic_conf.yml
watch: true
log:
level: INFO
filePath: "./logs.log"
accessLog: {}
dyanmic_conf.yml
http:
middlewares:
dashboard-auth:
basicAuth:
users:
- "admin:{{ env "DASHBOARD_PASSWORD" }}"
redirect-to-https:
redirectScheme:
scheme: https
permanent: true
routers:
dashboard-api:
entryPoints:
- dashboard
rule: "Host(`dashboard.domain.com`)"
service: api@internal
middlewares:
- dashboard-auth
secure-dashboard-api:
entryPoints:
- https
rule: "Host(`dashboard.domain.com`)"
service: api@internal
middlewares:
- dashboard-auth
tls:
certResolver: myhttpchallenge
https-redirect:
entryPoints:
- http
rule: "HostRegexp(`{host:.+}`)"
service: dummy
middlewares:
- redirect-to-https
services:
dummy:
loadBalancer:
servers:
- url: localhost
Registry setup
docker-compose.yml:
The certificate.crt and privatekey.key have been issued by Let's Encrypt and extracted from acme.json.
version: "3.9"
services:
registry:
image: registry:2.8.0
container_name: docker_registry
restart: always
ports:
- "5000:5000"
volumes:
- ./cert:/cert
- ./data:/data
- ./htpasswd:/auth/htpasswd
environments:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
- REGISTRY_HTTP_TLS_CERTIFICATE=/cert/certificate.crt
- REGISTRY_HTTP_TLS_KEY=/cert/privatekey.key
- REGISTRY_LOG_LEVEL=debug
- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data
labels:
- "traefik.enable=true"
- "traefik.http.services.registry.loadbalancer.server.port=5000"
- "traefik.http.services.registry.loadbalancer.server.scheme=https"
- "traefik.http.routers.registry.entrypoints=https"
- "traefik.http.routers.registry.tls.certresolver=myhttpchallenge"
- "traefik.http.routers.registry.tls=true"
- "traefik.http.routers.registry.rule=Host(`registry.domain.com`)"
networks:
- traefik