Docker-Registry behind Traefik HTTPS-Proxy - docker

I cant get docker-registry working behind a https-proxy. I use traefik for all containers on my server, so i will do with the registry. here is my docker-compose.yml for the registry service, it should use a letsencrypt cert:
version: "3.3"
services:
registry:
image: registry:latest
container_name: docker_registry
restart: always
volumes:
- /srv/docker-registry/data:/data
- /srv/docker-registry/auth:/auth
environment:
- REGISTRY_AUTH=htpasswd
- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
- REGISTRY_AUTH_HTPASSWD_PATH=/auth/.htpasswd
- REGISTRY_LOG_LEVEL=debug
- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.registry.entrypoints=http"
- "traefik.http.routers.registry.rule=Host(`registry.example.de`)"
- "traefik.http.middlewares.registry-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.registry.middlewares=registry-https-redirect"
- "traefik.http.services.registry-secure.loadbalancer.server.port=5000"
- "traefik.http.services.registry-secure.loadbalancer.server.scheme=https"
- "traefik.http.routers.registry-secure.entrypoints=https"
- "traefik.http.routers.registry-secure.tls.certresolver=http"
- "traefik.http.routers.registry-secure.tls=true"
- "traefik.http.routers.registry-secure.rule=Host(`registry.example.de`)"
networks:
- proxy
networks:
proxy:
external: true
The Error i Get on docker login:
Error response from daemon: Get "https://registry.example.de:5000/v2/": dialing registry.example.de:5000 static system has no HTTPS proxy: connecting to 202.xx.xxx.xxx:5000: dial tcp 202.xx.xxx.xxx:5000: connect: connection refused

registry:2 listens on http. Drop "traefik.http.services.registry-secure.loadbalancer.server.scheme=https"

Related

running traefik with a private docker registry as containers on different domains with self signed certs

I'm trying to set up a private Docker registry behind reverse proxy (with Traefik v2).
I have a computer with two local domains in the internal network
The private docker registry could work without a password
I created self-signed certificates
Without traefik I can push and pull images to the domain "docker-registry.mydomain.de:443".
If I include traefik I get certificate errors, bad gadway or a 404 error.
What am I doing wrong ?I have attached my code.
cat /srv/docker-compose/docker-compose.yml
version: '3.6'
services:
docker-registry:
image: registry:2
#ports:
##- 5000:5000
# - 443:443
environment:
- REGISTRY_HTTP_SECRET="mysecret"
- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/data
- REGISTRY_STORAGE_DELETE_ENABLED=true
- REGISTRY_HTTP_ADDR=0.0.0.0:443
- REGISTRY_HTTP_TLS_CERTIFICATE=/certs/docker-registry.mydomain.de.pem
- REGISTRY_HTTP_TLS_KEY=/certs/docker-registry.mydomain.de-key.pem
labels:
- traefik.enable=true
- traefik.http.routers.dr-http.entrypoints=http
- traefik.http.routers.dr-http.rule=Host(`docker-registry.mydomain.de`)
- traefik.http.routers.dr-http.middlewares=dr-https
- traefik.http.middlewares.dr-https.redirectscheme.scheme=https
- traefik.http.routers.dr.entrypoints=https
- traefik.http.routers.dr.rule=Host(`docker-registry.mydomain.de`)
- traefik.http.routers.dr.tls=true
- traefik.http.services.dr.loadbalancer.server.port=443
- traefik.docker.network=traefik-net
volumes:
- ./data:/data
- ./certs:/certs
networks:
- traefik-net
networks:
traefik-net:
external: true
cat /srv/traefik/docker-compose.yml
version: '3.6'
services:
reverse-proxy:
image: traefik:latest
networks:
- traefik-net
ports:
- 8080:8080
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./conf:/etc/traefik
- ./certs:/etc/ssl:ro
labels:
- traefik.enable=true
- traefik.http.routers.traefik-http.entrypoints=http
- traefik.http.routers.traefik-http.rule=Host(`traefik.mydomain.de`)
- traefik.http.routers.traefik-http.middlewares=traefik-https
- traefik.http.middlewares.traefik-https.redirectscheme.scheme=https
- traefik.http.routers.traefik.entrypoints=https
- traefik.http.routers.traefik.rule=Host(`traefik.mydomain.de`)
- traefik.http.routers.traefik.tls=true
- traefik.http.routers.traefik.service=api#internal
networks:
traefik-net:
external: true
cat /srv/traefik/conf/traefik.yml
insecureSkipVerify: true
api:
dashboard: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
watch: true
cat /srv/traefik/conf/dynamic.yml
tls:
certificates:
- certFile: /tools/certs/_wildcard.pem
keyFile: /tools/certs/_wildcard-key.pem
- certFile: /tools/certs/traefik.mydomain.de.crt
keyFile: /tools/certs/traefik.mydomain.de.key
- certFile: /tools/certs/docker-registry.mydomain.de.pem
keyFile: /tools/certs/docker-registry.mydomain.de.pem
all certifates are in the /srv/traefik/certs path.
Certificates are generated by mkcert and openssl tool.
The problem in code is docker registry accept only the intermediate.crt extension with crt not pem or csr. change that and you will succeed.

Is it possible to share ports between NGINX and Docker Container?

I have Ubuntu 18:04/NGINX VPS where I have a bunch of Laravel project blocks, all use ssl (certbot).
I wanted to deploy Nextcloud via Docker Compose on the same VPS:
version: "3"
services:
proxy:
image: jwilder/nginx-proxy:alpine
labels:
# labels needed by lets encrypt to identify container to generate certs in
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
container_name: nextcloud-proxy
networks:
- nextcloud_network
ports:
- 80:80
- 443:443
volumes:
- ./proxy/conf.d:/etc/nginx/conf.d:rw
- ./proxy/vhost.d:/etc/nginx/vhost.d:rw
- ./proxy/html:/usr/share/nginx/html:rw
- ./proxy/certs:/etc/nginx/certs:ro
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
restart: unless-stopped
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion:v1.12.1
container_name: nextcloud-letsencrypt
depends_on:
- proxy
networks:
- nextcloud_network
volumes:
- ./proxy/certs:/etc/nginx/certs:rw
- ./proxy/vhost.d:/etc/nginx/vhost.d:rw
- ./proxy/html:/usr/share/nginx/html:rw
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
db:
image: mariadb:10.5.1
container_name: nextcloud-mariadb
networks:
- nextcloud_network
volumes:
- ./db:/var/lib/mysql
- ./dbdumps:/var/dbdumps
- /etc/localtime:/etc/localtime:ro
environment:
- MYSQL_ROOT_PASSWORD=... # set me
- MYSQL_PASSWORD=... # set me
- MYSQL_DATABASE=... # set me
- MYSQL_USER=... # set me
restart: unless-stopped
redis:
container_name: nextcloud-redis
image: redis:5.0.8
restart: unless-stopped
networks:
- nextcloud_network
volumes:
- ./redis/data:/data
command: ["redis-server", "--appendonly yes"]
app:
image: nextcloud:18.0.2
container_name: nextcloud-app
networks:
- nextcloud_network
depends_on:
- letsencrypt
- proxy
- redis
- db
volumes:
- ./nextcloud:/var/www/html
- ./app/config:/var/www/html/config
- ./app/custom_apps:/var/www/html/custom_apps
- ./app/data:/var/www/html/data
- ./app/themes:/var/www/html/themes
- /etc/localtime:/etc/localtime:ro
environment:
- VIRTUAL_HOST=YOURDOMAINHERE # set me
- LETSENCRYPT_HOST=YOURDOMAINHERE # set me
- LETSENCRYPT_EMAIL=you#example.com # set me
restart: unless-stopped
networks:
nextcloud_network:
driver: bridge
When I run this I get:
ERROR: for 3f210d699b80_nextcloud-proxy Cannot start service proxy: driver failed programming
external connectivity on endpoint nextcloud-proxy
(2d76e425c94abb95da70a7d903bf8830d4e9192a512e17db1b39f76da85c7b97): Error starting userland proxy:
listen tcp 0.0.0.0:443: bind: address already in use
ERROR: for proxy Cannot start service proxy: driver failed programming external connectivity on
endpoint nextcloud-proxy (2d76e425c94abb95da70a7d903bf8830d4e9192a512e17db1b39f76da85c7b97): Error
starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use
ERROR: Encountered errors while bringing up the project.
Because this port is already in use.
If I stop NGINX on VPS and run docker-compose up -d again, everything is ok and Nextcloud service is accessible via URL.
I tried to change outside ports to
- 8080:80
- 4444:443
And rebuild it. Then I don't see the above error but everything is messed up - the url point to wrong domain...
Is it possible to tweak the proxy container settings somehow to resolve this?
2 services are unable to listen to the same port as you have found. Your laravel applications are already listening on ports 80/443, so when start your nextcloud containers, it won't be able to bind to those ports.
You'll have to have your jwilder/nginx-proxy:alpine act as a proxy to both the nextcloud container and the laravel servers. This can be done via your nginx configurations and mount it to your container (which you seem to be using the ./proxy/ directory):
https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
Although, if your VPS is able to have 2 IP addresses, then you are able to bind the laravel applications to one interface and your nextcloud proxy to the other which will also solve your problem. The first method is better practice as would allow you to scale your server better without having to add another IP address per-application.
https://docs.docker.com/config/containers/container-networking/

Configuring Nginx with Traefik

I'm new to Linux in general, and even newer to Traefik, and have been trying for some time to setup a nginx container to serve some AngularJS web pages, using Traefik as reverse-proxy. I have a small Ubuntu 20.4 server hosted on DigitalOcean (if that's of any relevance).
I have tried following a few different nginx tutorials, and messing with the settings on my own, to no success. It works if I run a simple command like:
$ docker run –name some-nginx -d -p 8888:80 nginx
But then I can only access it through myip:8888, and I would like to access it with a subdomain, i.e. docs.domain.com.
I managed to setup Traefik using a traefik.yml like that:
api:
dashboard: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
http:
acme:
email: email#email.com
storage: acme.json
httpChallenge:
entryPoint: http
And then docker-compose this file:
version: '3'
services:
traefik:
image: traefik:v2.0
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`monitor.domain.com`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:secret_password"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`monitor.domain.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=http"
- "traefik.http.routers.traefik-secure.service=api#internal"
networks:
proxy:
external: true
I also successfully set up a portainer:
version: '3'
services:
portainer:
image: portainer/portainer:latest
container_name: portainer
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.portainer.entrypoints=http"
- "traefik.http.routers.portainer.rule=Host(`manage.domain.com`)"
- "traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.portainer.middlewares=portainer-https-redirect"
- "traefik.http.routers.portainer-secure.entrypoints=https"
- "traefik.http.routers.portainer-secure.rule=Host(`manage.domain.com`)"
- "traefik.http.routers.portainer-secure.tls=true"
- "traefik.http.routers.portainer-secure.tls.certresolver=http"
- "traefik.http.routers.portainer-secure.service=portainer"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
- "traefik.docker.network=proxy"
networks:
proxy:
external: true
This way I can access both portainer and traefik subdomains, with SSL, no problems.
I tried using docker-compose files for nginx similar to the portainer one, using the volumes "./data:/usr/share/nginx/html:ro" and "./nginx.conf:/etc/nginx/nginx.conf:ro", as well some different nginx.conf options as exemplified in the Beginner's Guide from the official docs.
I would appreciate if someone could point ou which labels I should use on the docker-compose file and how to properly interface Traefik with the nginx config.

Nexus 3 as Docker Registry behind Traefik v.2 - pushing fails

On the same linux VM with docker v.19.03.11 I'm running:
Nexus:
version: '3.7'
services:
nexus:
container_name: nexus
image: sonatype/nexus3
volumes:
- nexus-data:/nexus-data
networks:
- web
ports:
- 8081
- 8082
- 8083
restart: always
labels:
- "traefik.enable=true"
- "traefik.docker.network=web"
# admin.nexus.xxx.intern
- "traefik.http.routers.nexus.rule=Host(`admin.nexus.xxx.intern`, `maven.nexus.itools.intern`)"
- "traefik.http.services.nexus.loadbalancer.server.port=8081"
- "traefik.http.routers.nexus.service=nexus"
- "traefik.http.routers.nexus.entrypoints=web"
# docker.nexus.xxx.intern
- "traefik.http.routers.docker.rule=Host(`docker.nexus.xxx.intern`)"
- "traefik.http.services.docker.loadbalancer.server.port=8083"
- "traefik.http.routers.docker.service=docker"
- "traefik.http.routers.docker.entrypoints=web"
networks:
web:
external: true
volumes:
nexus-data:
external: true
in Nexus Repository Manager Dashboard I created one hosted docker repository and assigned it port 8083.
and Traefik:
version: '3.7'
services:
traefik:
container_name: traefik
image: traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./conf:/conf
- ../ssl:/ssl:ro
networks:
- web
ports:
- 80:80
- 443:443
restart: always
command:
# Enabling docker provider
- "--providers.docker=true"
# Do not expose containers unless explicitly told so
- "--providers.docker.exposedbydefault=false"
# Enable API (listening on port 8080)
- "--api.insecure=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Enable the file provider to define routers / middlewares / services in file
# EMPTY AT THE TIME!
- "--providers.file.directory=/conf"
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.service=api#internal"
- "traefik.http.routers.traefik.rule=Host(`traefik.xxx.intern`)"
- "traefik.http.routers.traefik.entrypoints=web"
- "traefik.http.routers.traefik_tls.tls=true"
- "traefik.http.routers.traefik_tls.rule=Host(`traefik.xxx.intern`)"
- "traefik.http.routers.traefik_tls.entrypoints=websecure"
- "traefik.http.routers.traefik_tls.service=api#internal"
networks:
web:
external: true
I can login into the docker repository form anywhere:
docker login -u user -p password1234 docker.nexus.xxx.intern
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
but I cannot push into the registry:
docker push docker.nexus.xxx.intern/hello-world
The push refers to repository [docker.nexus.xxx.intern/hello-world]
af0b15c8625b: Preparing
error parsing HTTP 404 response body: invalid character 'p' after top-level value: "404 page not found\n"
When I expose the port 8083 and bypass Traefik, everything works fine and I can push into the Nexus Registry. The problem is I can only expose ports 80 and 443.
Did anyone have a similar issue and knows how to solve it?
Update 1
Have also tried with Harbor - the same result - cannot push behind traefik.
Same issue for me. I've tried
Option 1 : add prefix on path for v2 as Docker is putting a /v2 prefix
traefik.http.routers.docker.rule=Host(`docker.nexus.xxx.intern`) && PathPrefix(`/{version:(v1|v2)}/`)
Option 2 : add prefix to request and remove it with a middleware replacepathregex
traefik.http.middlewares.replace-path.replacepathregex.regex=^/(v1|v2)/(push|pull)/(.*)
traefik.http.middlewares.replace-path.replacepathregex.replacement=/$$1/$$3
traefik.http.routers.docker.rule=Host(`docker.nexus.xxx.intern`) && PathPrefix(`/{version:(v1|v2)}/push/`)
traefik.http.routers.nexus-registry-push.middlewares=replace-path
Try adding to the Nexus container in docker-compose file
environment:
- "REGISTRY_HTTP_RELATIVEURLS=true"

ACME certificates timeout with traefik

Hello!
I am having issues finding out the reason why I am getting this error. Tried googling it.
It seems to be an issue with dns lookup from the container.
Error in traefik log:
time="2020-01-30T12:12:12+01:00" level=error msg="Unable to obtain ACME certificate for domains \"traefik.xyz.se\": cannot get ACME client get directory at 'https://acme-v02.api.letsencrypt.org/directory': Get https://acme-v02.api.letsencrypt.org/directory: dial tcp: lookup acme-v02.api.letsencrypt.org on 127.0.0.11:53: read udp 127.0.0.1:54773->127.0.0.11:53: i/o timeout" providerName=cloudflare.acme routerName=traefik-secure#docker rule="Host(`traefik.xyz.se`)"
time="2020-01-30T12:12:32+01:00" level=error msg="Unable to obtain ACME certificate for domains \"hivemq.xyz.se\": cannot get ACME client get directory at 'https://acme-v02.api.letsencrypt.org/directory': Get https://acme-v02.api.letsencrypt.org/directory: dial tcp: lookup acme-v02.api.letsencrypt.org on 127.0.0.11:53: read udp 127.0.0.1:53671->127.0.0.11:53: i/o timeout" rule="Host(`hivemq.xyz.se`)" providerName=cloudflare.acme routerName=hivemq-secure#docker
Unable to lookup google from within traefik container. Don't know if this is working as intended?
/o/a/traefik> docker exec -it traefik /bin/sh
/ # nslookup google.se
nslookup: can't resolve '(null)': Name does not resolve
nslookup: can't resolve 'google.se': Try again
/ #
Traefik docker-compose.yaml
version: '3'
services:
traefik:
image: traefik:v2.1
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
environment:
- CF_API_EMAIL=redacted
- CF_API_KEY=redacted
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
- ./data/config.yml:/config.yml:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.xyz.se`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=redacted"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.xyz.se`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=cloudflare"
- "traefik.http.routers.traefik-secure.tls.domains[0].main=xyz.se"
- "traefik.http.routers.traefik-secure.tls.domains[0].sans=*.xyz.se"
- "traefik.http.routers.traefik-secure.service=api#internal"
networks:
proxy:
external: true
data/traefik.yml:
api:
dashboard: true
debug: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /config.yml
certificatesResolvers:
cloudflare:
acme:
email: redacted
storage: acme.json
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 0
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
Service example (hivemq) docker-compose.yml:
version: "3"
services:
hivemq:
image: hivemq/hivemq4
container_name: hivemq
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- 1883:1883
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.hivemq.entrypoints=http"
- "traefik.http.routers.hivemq.rule=Host(`hivemq.xyz.se`)"
- "traefik.http.routers.hivemq.middlewares=https-redirect#file"
- "traefik.http.routers.hivemq-secure.middlewares=secured#file"
- "traefik.http.routers.hivemq-secure.entrypoints=https"
- "traefik.http.routers.hivemq-secure.rule=Host(`hivemq.xyz.se`)"
- "traefik.http.routers.hivemq-secure.tls=true"
- "traefik.http.routers.hivemq-secure.service=hivemq"
- "traefik.http.services.hivemq.loadbalancer.server.port=8080"
- "traefik.docker.network=proxy"
networks:
- internal
- proxy
networks:
proxy:
external: true
internal:
external: false
I have also tried reinstalling docker-ce, didn't help.
I had a similar issue and it was due to a bug of Docker: all my containers had lost their connection to the internet but they were all already removed for maintenance puprose so I couldn't see it.
In the logs, cannot get ACME client get directory means that Traefik cannot connect to Let's Encrypt url.
I fixed it by:
Removing Traefik stack
Pruning networks so traefik-public was removed
Restarting Docker service
If it's not enough, you can try these:
Try to restart the Docker Engine, which will reset any iptables rules (assuming you are using Docker on Linux)
Try to restart your whole machine
Try to disable (temporary) the firewall of your machine to verify that it fixes the issue
As mentioned here: https://community.containo.us/t/cannot-create-renew-acme-certificate-cannot-get-acme-client-get-directory/2469/2
I gave a rapid look around concerning Docker bugs about loosing connection and seems to be a mess, for years: https://github.com/moby/moby/issues/15172
Not a docker specialist but I had a similar issue and fixed it by activating ipv6 on docker daemon :
% grep ipv6 /etc/docker/daemon.json
"ipv6": true`
You need to reload docker daemon then
% sudo systemctl reload docker

Resources