How to set-up Traefik as a reverse proxy for Docker containers
When using docker for managing services, one important thing is how to publish the service to the internet, this typically requires configuring a domain, obtaining an SSL certificate, and other related tasks. However, performing these tasks manually can be tedious and time-consuming.
The common approach for publishing service
Nginx is a widely-used open-source web server frequently used as a reverse proxy server. The standard configuration for using Nginx as a reverse proxy outside of Docker typically involves defining an upstream server block that specifies the IP address and port number of the backend server and then using the proxy_pass
directive to forward incoming requests to the backend server.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
When using Docker, if Nginx and the container are connected to the same Docker network, Nginx can communicate with the container using the container's hostname. Therefore, the configuration could be rewritten to this:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend-container:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Service publishing with Traefik
Traefik is a modern reverse proxy that is designed for making deploying services simple. It can use service discovery to configure the services and can work with Let's Encrypt to automatically generate certificates.
docker-compose.yml
:
version: '3.9'
services:
traefik:
image: "traefik:v2.6"
container_name: "traefik"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "./traefik.toml:/etc/traefik/traefik.toml"
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
outbound:
name: outbound
traefik.toml
:
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.forwardedHeaders]
insecure = true
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"
[certificatesResolvers.letsencrypt.acme]
email = "janedoe@example.com"
storage = "/letsencrypt/acme.json"
[certificatesResolvers.letsencrypt.acme.tlsChallenge]
[api]
dashboard = true
insecure = true
[providers.docker]
exposedByDefault = false
watch = true
network = "outbound"
Finally, you need to create an empty letsencrypt/acme.json
file. Then when we want to publish the service, we can do the following:
version: '3.9'
services:
backend:
image: backend
labels:
- traefik.enable=true
- traefik.docker.network=outbound
- traefik.http.routers.backend.rule=Host(`example.com`)
- traefik.http.routers.backend.entrypoints=websecure
- traefik.http.routers.backend.tls.certresolver=letsencrypt
networks:
- outbound
networks:
outbound:
external: true
name: outbound