In this post I will show you how to connect multiple docker-compose files in different networks with traefik as a reverse proxy
.Sometimes kubernetes is just to much for a small project and you find yourself creating a good old docker-compose file. This time it’s about a simple wordpress setup but with in mind that we might add later more services like another wordpress page on the same VM. This brings in a proxy so we are able to route traffic incoming to port 80/443 to different services (wordpress instances). As a second requirement we want to handle the different services in separate docker-compose files and last but not least we want SSL via Let’s Encrypt.
Prerequisites
- docker-compose
- A sub-/domain you can point to a VM with a public IP so Let’s Encrypt can do it’s magic
Traefik
Traefik is an easy to use proxy with docker in mind starting from day one. It was the first proxy I am aware of which reacts on docker labels for service discovery. It comes with a nice UI and supports Let’s Encrypt.
Create a directory named traefik and put the following docker-compose.yaml inside it:
version: '3.8'
services:
proxy:
image: traefik:v2.3
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
command:
- --providers.docker
- --log.level=DEBUG
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --api.dashboard=true
- --api.insecure=true
- --certificatesresolvers.le.acme.email=yourmail@example.com
- --certificatesresolvers.le.acme.storage=/acme/acme.json
- --certificatesresolvers.le.acme.tlschallenge=true
ports:
- "80:80"
- "443:443"
# traefik webui
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# feel free to mount it somewhere else
- /mnt/traefik/acme:/acme
restart:
always
networks:
- traefik
networks:
traefik:
name: traefik-net
With a docker-compose up
we tell treafik to do the following:
- enable the docker provider
- set log level to debug for easy debugging
- don’t add every docker service to traefik
- listen on port 80 and port 443 with the (free to choose) entrypoint names web and websecure
- redirect http traffic to https
- enable the dashboard in the insecure mode (for production you should use the secure mode)
- configure Let’s encrypt
- listen to docker.sock for service discovery
- use a volume to store Let’s encrypt certs (acme.json)
- create a docker network named traefik-net
That last one is essential when we want to join the traefik network with other services in different docker-compose files.
Check the dashboard by visiting http://yourserver:8080/dashboard/
Nice! The dashboard shows up with our named entrypoints.
WordPress
Create another directory named wordpress with the following docker-compose.yaml
version: '3.8'
services:
db:
image: 'mariadb:10.5.8'
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
volumes:
- '/mnt/mysql:/var/lib/mysql'
restart: always
environment:
MYSQL_ROOT_PASSWORD: 'verysecure'
MYSQL_DATABASE: wordpress
MYSQL_USER: 'wordpress-user'
MYSQL_PASSWORD: 'secureme'
networks:
- backend
wordpress:
image: wordpress:5.6.0
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
restart:
always
volumes:
- /mnt/wordpress:/var/www/html
environment:
WORDPRESS_ADMIN_PASSWORD: 'againsecure'
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: 'wordpress-user'
WORDPRESS_DB_PASSWORD: 'secureme'
WORDPRESS_DB_NAME: wordpress
labels:
- traefik.enable=true
- traefik.http.routers.wordpress.rule=Host(`mypage.de`)
- traefik.http.routers.wordpress.entrypoints=websecure
- traefik.http.routers.wordpress.tls.certresolver=le
- traefik.docker.network=traefik-net
depends_on:
- db
networks:
- backend
- web
networks:
web:
external:
name: traefik-net
backend:
In general this is a straight forword docker-compose.yaml for wordpress so I will only explain the traefik and network parts. At line 39 we start defining labels which will picked up by traefik.
traefik.enable=true
Because we used providers.docker.exposedbydefault=false
the mysql service will be ignored and this label tells traefik to take care off the wordpress service.
traefik.http.routers.wordpress.rule=Host(mypage.de)
Configures a router named “wordpress” to listen for requests with the host header “mypage.de”.
traefik.http.routers.wordpress.entrypoints=websecure
The wordpress router should listen to the named entrypoint “websecure” which means port 443 in our case.
traefik.http.routers.wordpress.tls.certresolver=le
Use the TLS challenge configured in “le” to generate and renew ACME certificates.
traefik.docker.network=traefik-net
Tell traefik to use “traefik-net” as the network to route requests to this service.
networks:
- backend
- web
Put the wordpress service in a network named “backend” so it can speak to mysql and in a network named “web”.
networks:
web:
external:
name: traefik-net
backend:
Defines the network “web” which points to an external network with the name “traefik-net”. We created “traefik-net” in the first docker-compose.yaml and now we join it with our wordpress service. This is important to allow communication between traefik and our wordpress service. Last but not least we create a regular docker network “backend” where the service mysql and wordpress can talk to each other.
Fire it up with docker-compose up and check the routers section in the traefik dashboard.
Our router “wordpress@docker” should show up . The suffix “@docker” is assigned by traefik for every docker router.
Point your browser to https://mypage.de and the wordpress installation page should show up.
You can now create more docker-compose.yaml files with another wordpress setup or anything else routed by traefik. Just check that you defined the needed traefik lables and you joined the “treafik-net” network so traefik can reach your service.