docker4drupal
docker4drupal copied to clipboard
Traefik v2 https support
I am am trying to up the latest version of docker4drupal to work with Traefik v2. I had it working previously with v1.x of Traefik but am struggling to transition to configure v2.
I have tried to follow the lets encrypt guidelines on traefik website but there seems to be some issue with generating the certificate on a dev environment.
Any guidelines on how to achieve this would be welcome.
https://blog.containo.us/traefik-2-0-docker-101-fc2893944b9d
Hi, if anyone is interested, I got Traefik 2.0 working with TLS with support for multiple projects.
Here is my setup:
docker-compose.yml
nginx:
image: wodby/nginx:$NGINX_TAG
container_name: "${PROJECT_NAME}_nginx"
depends_on:
- php
environment:
NGINX_STATIC_OPEN_FILE_CACHE: "off"
NGINX_ERROR_LOG_LEVEL: debug
NGINX_BACKEND_HOST: php
NGINX_SERVER_ROOT: /var/www/html/web
NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET
volumes:
- ./:/var/www/html
- docker-sync-unison:/var/www/common # Docker-sync for macOS users
labels:
- "traefik.http.routers.${PROJECT_NAME}_nginx.entrypoints=web"
- "traefik.http.middlewares.${PROJECT_NAME}_https_nginx.redirectscheme.scheme=https"
- "traefik.http.routers.${PROJECT_NAME}_https_nginx.rule=Host(`${PROJECT_NAME}.docker.localhost`)"
- "traefik.http.routers.${PROJECT_NAME}_https_nginx.entrypoints=web-secure"
- "traefik.http.routers.${PROJECT_NAME}_https_nginx.tls=true"
traefik.yml
Place it separately from your projects and start with docker-compose -f traefik.yml up
version: '3'
services:
traefik:
image: traefik:v2.0
command:
- "--api.insecure=true"
- "--providers.docker"
- "--log.level=DEBUG"
- "--configFile=./myconfigfile.toml"
- "--entrypoints.web.address=:80"
- "--entrypoints.web-secure.address=:443"
networks:
- "xxxx"
ports:
- '80:80'
- '8080:8080'
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./certs/:/certs/
container_name: traefik
networks:
xxxx:
external:
name: xxxx_default
myconfigfile.toml
# dynamic configuration
[http.routers]
[http.routers.Router-1]
rule = "Host(`docker.localhost`)"
service = "service-id"
# will terminate the TLS request
[http.routers.Router-1.tls]
options = "myTLSOptions"
[[tls.certificates]]
certFile = "/certs/cert.pem"
keyFile = "/certs/key.pem"
[tls.options]
[tls.options.default]
minVersion = "VersionTLS12"
[tls.options.myTLSOptions]
minVersion = "VersionTLS13"
cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
]
To enable https you need to do only 2 steps
- Enable automatic cetrifs generation
services:
traefik:
image: "traefik:v2.0.0"
command:
# add these lines
- --entrypoints.websecure.address=:443
- [email protected]
- --certificatesresolvers.le.acme.storage=/acme.json
- --certificatesresolvers.le.acme.tlschallenge=true
ports:
# add 443 port
- "443:443"
[email protected] - change on yours email address
- Enable automatic certifs generation for container (e.g. nginx)
nginx:
image: wodby/nginx:$NGINX_TAG
container_name: "${PROJECT_NAME}_nginx"
depends_on:
- php
environment:
NGINX_STATIC_OPEN_FILE_CACHE: "off"
NGINX_ERROR_LOG_LEVEL: debug
NGINX_BACKEND_HOST: php
NGINX_SERVER_ROOT: /var/www/html/web
NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET
volumes:
- ./:/var/www/html
labels:
- "traefik.http.routers.${PROJECT_NAME}_nginx.rule=Host(`${PROJECT_BASE_URL}`)"
# add these lines
- "traefik.http.routers.${PROJECT_NAME}_nginx.tls.certresolver=le"
- "traefik.http.routers.${PROJECT_NAME}_nginx.entrypoints=websecure"
Complete.
Could you explain it? I use it for local development so no LE ACME for me. I use mkcert to generate certificates and Traefik works with both http and https. However it shows the website in http, and the "404 page not found" error in https. How to setup to redirect https traffic to the other containers (Apache, phpMyAdmin etc.) on port 80 so that Traefik does the TLS termination here?
docker-compose.yml
nginx:
image: wodby/nginx:$NGINX_TAG
container_name: "${PROJECT_NAME}_nginx"
depends_on:
- php
environment:
NGINX_STATIC_OPEN_FILE_CACHE: "off"
NGINX_CLIENT_MAX_BODY_SIZE: 10G
NGINX_ERROR_LOG_LEVEL: debug
NGINX_BACKEND_HOST: php
NGINX_VHOST_PRESET: php
NGINX_SERVER_ROOT: /var/www/html/public
NGINX_STATIC_EXT_REGEX: css|cur|js|htc|ico|xml|otf|ttf|eot|woff|woff2|svg|mp4|svgz|ogg|ogv|pdf|pptx?|zip|tgz|gz|rar|bz2|doc|xls|exe|tar|mid|midi|wav|bmp|rtf|txt|map
volumes:
- ./:/var/www/html
labels:
- "traefik.enable=true"
- "traefik.http.routers.${PROJECT_NAME}_nginx.entrypoints=http"
- "traefik.http.routers.${PROJECT_NAME}_nginx.rule=Host(`${PROJECT_NAME}.localhost`)"
- "traefik.http.middlewares.${PROJECT_NAME}_nginx-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.${PROJECT_NAME}_nginx.middlewares=${PROJECT_NAME}_nginx-https-redirect"
- "traefik.http.routers.${PROJECT_NAME}_nginx-secure.entrypoints=https"
- "traefik.http.routers.${PROJECT_NAME}_nginx-secure.rule=Host(`${PROJECT_NAME}.localhost`)"
- "traefik.http.routers.${PROJECT_NAME}_nginx-secure.tls=true"
- "traefik.http.routers.${PROJECT_NAME}_nginx-secure.service=${PROJECT_NAME}_nginx"
- "traefik.http.services.${PROJECT_NAME}_nginx.loadbalancer.server.port=80"
traefik:
image: traefik
container_name: traefik
security_opt:
- no-new-privileges:true
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
- ./traefik.dynamic.yml:/traefik.dynamic.yml:ro
- ./certs:/certs
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.localhost`)"
- "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.localhost`)"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.service=api@internal"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
traefik.yml
api:
dashboard: true
log:
level: DEBUG
filePath: "debug.log"
format: json
accessLog:
filePath: "access.log"
bufferingSize: 100
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
file:
filename: /traefik.dynamic.yml
watch: true
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
traefik.dynamic.yml
tls:
stores:
default:
defaultCertificate:
certFile: /certs/localhost+5.pem
keyFile: /certs/localhost+5-key.pem
certificates:
- certFile: /certs/localhost+5.pem
keyFile: /certs/localhost+5-key.pem
certificates are generated by mkcert for ${PROJECT_NAME}.localhost, varnish.${PROJECT_NAME}.localhost traefik.localhost and localhost.
Need to replace ${PROJECT_NAME} to your project name.
Can folks actually explain the examples beyond just pasting code above? The setup for v1 was pretty simple but v2 was not working at all.
However it shows the website in http, and the "404 page not found" error in https.
This is exactly my experience. I was looking here, which a handful of places on the net keep referencing: https://containo.us/blog/traefik-2-0-docker-101-fc2893944b9d/
I found that article confusing, the blog post links to multiple files in git and each one is slightly different.
To get HTTP -> HTTPS redirection working, I finally stumbled upon this post. Adapting that, I was finally able to get a self signed certificate and https redirection working.
Here is what I have:
apache:
image: wodby/apache:$APACHE_TAG
container_name: "${PROJECT_NAME}_apache"
environment:
APACHE_LOG_LEVEL: debug
APACHE_BACKEND_HOST: php
APACHE_VHOST_PRESET: php
APACHE_DOCUMENT_ROOT: /var/www/html/docroot
volumes:
- ./:/var/www/html:cached # User-guided caching
labels:
- traefik.http.middlewares.${PROJECT_NAME}_apache_https.redirectscheme.scheme=https
- traefik.http.routers.${PROJECT_NAME}_apache.entrypoints=web
- traefik.http.routers.${PROJECT_NAME}_apache.rule=Host(`${PROJECT_BASE_URL}`)
- traefik.http.routers.${PROJECT_NAME}_apache.middlewares=${PROJECT_NAME}_apache_https@docker
- traefik.http.routers.${PROJECT_NAME}_apache_https.rule=Host(`${PROJECT_BASE_URL}`)
- traefik.http.routers.${PROJECT_NAME}_apache_https.tls=true
- traefik.http.routers.${PROJECT_NAME}_apache_https.entrypoints=websecure
traefik:
image: traefik:v2.0
container_name: "${PROJECT_NAME}_traefik"
command:
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --providers.docker
- --providers.file.directory=/etc/traefik/dynamic_conf
ports:
- '80:80'
- '443:443'
volumes:
- ./tools/certs:/tools/certs
- ./tools/traefik/config.yml:/etc/traefik/dynamic_conf/conf.yml:ro
- /var/run/docker.sock:/var/run/docker.sock
traefik config.yml:
tls:
certificates:
- certFile: /tools/certs/cert.crt
keyFile: /tools/certs/cert.key
Note that the labels in each service are very particular about format, and double check you have no spelling errors. The apache labels are important, as it describes the entrypoints and what to do with them.
This was a lot harder to figure out than I was expecting, and depending on where you look on the internet there are various write ups on what to do. Nothing worked except for the blog post above. The contanious one is confusing and was of no help whatsoever.
I am using a self signed certificate (openssl, but mkcert is probably very similar) so we can get local https with browser trust supported - my containers can't be seen by Lets Encrypt since these are for local development only, so no certificate is ever sent back.
This answer was helpful: https://stackoverflow.com/a/60072381/295112
IMO it would be super helpful for docker4drupal to come with HTTPS enabled and redirecting by default since that is how all production applications are running these days anyway. It shouldn't take hours to figure out how to make it happen (blaming traefik not d4d maintainers) and it seems we are not the only ones.
Unfortunately I haven't had luck with getting the http to https redirect to work.
I keep getting field not found redirectscheme
and when commenting out the first line, I also then get middleware \"docker4drupal_apache_https@docker\" does not exist"
.
Otherwise the configuration worked for https and http.
I think the issue for me ended up being - traefik.http.routers.${PROJECT_NAME}_apache.middlewares=${PROJECT_NAME}_apache_https@docker
, and removing @docker
from the end. Then Kevin's configuration worked for me.
It helped me. There are enough instructions to understand how to configure that
Note: remember that if you make a mistake in the labels with route name you will get a 404 error in the browser without any logs for traefik.
https://docs.traefik.io/user-guides/docker-compose/acme-tls/
nginx:
image: wodby/nginx:$NGINX_TAG
container_name: "${PROJECT_NAME}_nginx"
depends_on:
- php
environment:
NGINX_STATIC_OPEN_FILE_CACHE: "off"
NGINX_ERROR_LOG_LEVEL: debug
NGINX_BACKEND_HOST: php
NGINX_SERVER_ROOT: /var/www/html/docroot
NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET
# NGINX_DRUPAL_FILE_PROXY_URL: http://example.com
volumes:
- ./www:/var/www/html
labels:
- "traefik.enable=true"
- "traefik.http.routers.${PROJECT_NAME}_nginx.rule=Host(`${PROJECT_BASE_URL}`)"
- "traefik.http.routers.${PROJECT_NAME}_nginx.entrypoints=websecure"
- "traefik.http.routers.${PROJECT_NAME}_nginx.tls.certresolver=myresolver"
traefik:
image: traefik
container_name: "traefik"
command:
#- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
#- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.myresolver.acme.email=your_email@gmail.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "8080:8080"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
It helped me. There are enough instructions to understand how to configure that
https://docs.traefik.io/user-guides/docker-compose/acme-tls/
That page mentions:
For the TLS challenge you will need:
- A publicly accessible host allowing connections on port 443 with docker & docker-compose installed.
Are we not talking about local dev environments here?? So this is unrelated + again, everyone, please stop just dumping code here without any further explanation.
On an older Traefik version on a LOCAL development environment, on macOS, I got HTTPS working the following way:
docker-compose.yml:
traefik:
image: traefik:v1.7.16-alpine
container_name: "${PROJECT_NAME}_traefik"
command: -c /dev/null --web --docker --logLevel=INFO --defaultEntryPoints='https' --entryPoints="Name:https Address::443 TLS:/certs/mysite_cert.pem,/certs/mysite_cert-key.pem" --entryPoints="Name:http Address::80 Redirect.EntryPoint:https"
ports:
- '8000:80'
- '443:443'
volumes:
- ./certs:/certs/
- /var/run/docker.sock:/var/run/docker.sock
mysite_cert.pem
and mysite_cert-key.pem
needs to be adjusted to your own certificates naming.
I generated self-signed certificates using mkcert, see: https://github.com/FiloSottile/mkcert/blob/master/README.md
I placed the certificates in a certs
folder, at the project root (where docker-compose.yml file is).
There is no redirection. Only direct access on HTTPS, but it works and is sufficient for my needs.
Note that I was still getting errors with the above settings until I restarted Docker desktop then all went fine.
Hello everyone
Can anyone drop a complete example of a working configuration for traefik 2? I tried everything, and I still can't configure it.
The maximum that was achieved is that an empty acme.json file appears and, accordingly, the certificate is not valid in the browser
I can't post a full example because there's a lot of information that's not relevant in the YAML file, but I can post the relevant sections for my apache, mailhog, adminer, and traefik service definitions.
- Generate a self-signed certificate with openssl in a
certs/
directory (default.crt, default.key) within docker4drupal directory. - Create the following traefik.yml file in the docker4drupal directory.
tls:
certificates:
- certFile: /certs/default.crt
keyFile: /certs/default.key
- Configure the traefik service in docker-compose.yml
traefik:
image: traefik:v2.1
container_name: "${PROJECT_NAME}_traefik"
command:
- --entrypoints.db.address=:5432
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --api.insecure=true
- --providers.docker
- --providers.file.directory=/etc/traefik/dynamic_conf
ports:
- '80:80'
- '443:443'
- '8080:8080' # Dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.yml:/etc/traefik/dynamic_conf/conf.yml:ro
- ./certs:/certs
- Add the labels to relevant services in docker-compose.yml
postgresql:
labels:
- "traefik.tcp.services.postgresql.loadbalancer.server.port=5432"
- "traefik.tcp.routers.${PROJECT_NAME}_db.entrypoints=db"
- "traefik.tcp.routers.${PROJECT_NAME}_db.rule=HostSNI(`${PROJECT_BASE_URL}`)"
- "traefik.tcp.routers.${PROJECT_NAME}_db.service=postgresql"
apache:
labels:
- "traefik.http.middlewares.${PROJECT_NAME}_apache_https.redirectscheme.scheme=https"
- "traefik.http.routers.${PROJECT_NAME}_apache.entrypoints=web"
- "traefik.http.routers.${PROJECT_NAME}_apache.middlewares=${PROJECT_NAME}_apache_https"
- "traefik.http.routers.${PROJECT_NAME}_apache.rule=Host(`${PROJECT_BASE_URL}`)"
- "traefik.http.routers.${PROJECT_NAME}_apache_https.rule=Host(`${PROJECT_BASE_URL}`)"
- "traefik.http.routers.${PROJECT_NAME}_apache_https.tls=true"
- "traefik.http.routers.${PROJECT_NAME}_apache_https.entrypoints=websecure"
adminer:
labels:
- "traefik.http.routers.${PROJECT_NAME}_adminer.rule=Host(`admin.${PROJECT_BASE_URL}`)"
mailhog:
labels:
- "traefik.http.services.${PROJECT_NAME}_mailhog.loadbalancer.server.port=8025"
- "traefik.http.routers.${PROJECT_NAME}_mailhog.rule=Host(`mail.${PROJECT_BASE_URL}`)"
T̶h̶i̶s̶ ̶p̶o̶s̶t̶ ̶m̶u̶s̶t̶ ̶b̶e̶ ̶p̶i̶n̶n̶e̶d̶ ̶s̶o̶m̶e̶h̶o̶w̶.̶ All answers in this thread are trash (read: haven't worked for me). This yaml from this article actually works! Pay attention to the comments in the end of file.
In case of Docker4Drupal with nginx to enable https the code will be this one below:
nginx:
image: wodby/nginx:$NGINX_TAG
container_name: "${PROJECT_NAME}_nginx"
depends_on:
- php
environment:
NGINX_STATIC_OPEN_FILE_CACHE: "off"
NGINX_ERROR_LOG_LEVEL: debug
NGINX_BACKEND_HOST: php
NGINX_SERVER_ROOT: /var/www/html/web
NGINX_VHOST_PRESET: $NGINX_VHOST_PRESET
volumes:
- ./:/var/www/html:cached
labels:
- "traefik.http.routers.${PROJECT_NAME}_nginx.rule=Host(`${PROJECT_BASE_URL}`)"
- "traefik.http.routers.${PROJECT_NAME}_nginx.middlewares=auth"
- "traefik.http.routers.${PROJECT_NAME}_nginx.entrypoints=websecure"
- "traefik.http.routers.${PROJECT_NAME}_nginx.tls.certresolver=leresolver"
- "traefik.http.middlewares.auth.basicauth.users=user:$$apr1$$q8eZFHjF$$Fvmkk//V6Btlaf2i/ju5n/" # user/password
traefik:
image: traefik:v2.0
container_name: "${PROJECT_NAME}_traefik"
command:
- --api.insecure=true
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
# ...
- --certificatesresolvers.leresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
- [email protected]
- --certificatesresolvers.leresolver.acme.storage=/acme.json
- --certificatesresolvers.leresolver.acme.tlschallenge=true
ports:
- '80:80'
- '443:443'
- '8080:8080' # Dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./certs:/certs/
- "./acme.json:/acme.json"
It is for dev environment and also activates Traefik Dashboard.
for me solution from @dmitrymenshikov worked locally. I don't need automatic redirect. No other things are required. Tested on Drupal 9
When using cert resolvers with '.internal' domain I seemed to have an issue with the cert resolvers. @kevinquillen answer worked for me, albeit switching from nginx to apache.
Not sure it there is any update on this as this is quite an old thread now but had issues adding a self signed cert when updating from 3 to 3.7 or specifically to traefik v2?