Getting Started With Traefik
This tutorial will show you how to get started with using Traefik locally, so that you can get to grips with it, before you dive into doing something more complicated, such as use it in a Kubernetes or Docker-Swarm cluster.
Related Posts
Table Of Contents
- What is Traefik?
- Deploying Traefik
- Deploy Example Web Service
- Configure Wildcard Certificate
- Redirecting HTTP to HTTPS
- Exposed By Default
- References
What is Traefik?
Traefik is a popular reverse proxy and load balancer that makes deploying microservices easy. This starts becoming essential quite quickly when you have a lot of web services that want to be accessed on ports 80/443. Traefik can also be quite handy at being the handler and termination point for SSL, so that your underlying services do not need to worry about them.
You can read more about it on their website.
Deploying Traefik
Static Config File
Before doing anything, you probably want to download the sample static config file, and call it static-config.yml
, and uncomment most of it,
applying settings that you want. I found that not doing so (expecting the defaults),
resulted in the image not working.
You can download the sample from the website, or you can copy my example below:
################################################################
#
# Configuration sample for Traefik v2.
#
# For Traefik v1: https://github.com/traefik/traefik/blob/v1.7/traefik.sample.toml
#
################################################################
################################################################
# Global configuration
################################################################
global:
checkNewVersion: true
sendAnonymousUsage: true
################################################################
# EntryPoints configuration
################################################################
# EntryPoints definition
#
# Optional
#
entryPoints:
web:
address: :80
websecure:
address: :443
################################################################
# Traefik logs configuration
################################################################
# Traefik logs
# Enabled by default and log to stdout
#
# Optional
#
log:
# Log level
#
# Optional
# Default: "ERROR"
#
level: ERROR
# Sets the filepath for the traefik log. If not specified, stdout will be used.
# Intermediate directories are created if necessary.
#
# Optional
# Default: os.Stdout
#
filePath: log/traefik.log
# Format is either "json" or "common".
#
# Optional
# Default: "common"
#
format: json
################################################################
# Access logs configuration
################################################################
# Enable access logs
# By default it will write to stdout and produce logs in the textual
# Common Log Format (CLF), extended with additional fields.
#
# Optional
#
accessLog:
# Sets the file path for the access log. If not specified, stdout will be used.
# Intermediate directories are created if necessary.
#
# Optional
# Default: os.Stdout
#
filePath: log/traefik-access.log
# Format is either "json" or "common".
#
# Optional
# Default: "common"
#
format: json
################################################################
# API and dashboard configuration
################################################################
# Enable API and dashboard
#
# Optional
#
api:
# Enable the API in insecure mode
#
# Optional
# Default: false
#
insecure: true
# Enabled Dashboard
#
# Optional
# Default: true
#
dashboard: true
################################################################
# Ping configuration
################################################################
# Enable ping
#ping:
# Name of the related entry point
#
# Optional
# Default: "traefik"
#
# entryPoint: traefik
################################################################
# Docker configuration backend
################################################################
providers:
# Enable Docker configuration backend
docker:
# Docker server endpoint. Can be a tcp or a unix socket endpoint.
#
# Required
# Default: "unix:///var/run/docker.sock"
#
endpoint: "unix:///var/run/docker.sock"
# Default host rule.
#
# Optional
# Default: "Host(`{{ normalize .Name }}`)"
#
# defaultRule: Host(`{{ normalize .Name }}.docker.localhost`)
# Expose containers by default in traefik
#
# Optional
# Default: true
#
exposedByDefault: true
static-config.yml
rather than traefik.yml
to save confusion later when we will need to create other configuration files.
This config file relates to anywhere in the documentation where it refers to "static" configuration, rather than something like "dynamic".
Create Network
Next, we want to create a network that Traefik will run on, that other services can later join, for which Traefik will act as a reverse proxy:
docker network create traefik-net
Deploy Traefik Container
Now we are ready to deploy Traefik. Here we will run the image, using the static-config.yml
config file we created earlier.
docker run \
--name traefik \
--detach \
--network traefik-net \
--publish 8080:8080 \
--publish 80:80 \
--volume $PWD/static-config.yml:/etc/traefik/traefik.yml \
--volume /var/run/docker.sock:/var/run/docker.sock \
traefik:v2.8
- By using the static config file, we don't need to override the command/entrypoint like other tutorials do.
- Using a volume for the Docker socket, allows Traefik to listen to events, so it can pick up on Docker events when other containers get deployed. This allows it to then automatically act as their reverse proxy.
- The dashboard is exposed on port 8080, whereas port 80 is used for the "insecure" web connections.
Docker Compose Example
The Docker Compose equivalent is below if you need it:
version: "3.9"
networks:
traefik-net:
external: true
services:
reverse-proxy:
container_name: traefik
image: traefik:v2.8
networks:
- traefik-net
ports:
- "80:80"
- "8080:8080"
volumes:
- ./static-config.yml:/etc/traefik/traefik.yml:ro # Provide the config file.
- /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
Dashboard
If you go to localhost:8080
in your browser, you should now see a dashboard for managing Traefik (if you used the same configuration settings, whereby the dashboard was enabled).
Deploy Example Web Service
Now lets test it by deploying an example web service that wants to be exposed on port 80.
docker run \
--detach \
--name whoami1 \
--network traefik-net \
--label "traefik.http.routers.whoami.rule=Host(\"whoami.docker.localhost\")" \
traefik/whoami
- The key thing here is the
--label
. This tells Traefik that this container wants to be served up, when a request comes in forwhoami.docker.localhost
. - The
--network traefik-net
tells the container to join thetraefik-net
network that you created earlier, allowing Traefik to communicate with the container.
Docker Compose Example
The Docker Compose equivalent is below if you need it.
version: "3.9"
networks:
traefik-net:
external: true
services:
whoami:
container_name: whoami
image: traefik/whoami
networks:
- traefik-net
labels:
- traefik.http.routers.whoami.rule=Host("whoami.docker.localhost")
Check It Works
Now if you go to whoami.docker.localhost
in your web browser, you should see some output from the whoami
service similar to below:
Hostname: ff8f10b92857
IP: 127.0.0.1
IP: 172.31.0.3
RemoteAddr: 172.31.0.2:56022
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.5
Dnt: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Sec-Gpc: 1
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 172.31.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: cbfbb38ae0b0
X-Real-Ip: 172.31.0.1
Configure Wildcard Certificate
If you generate your own wildcard certificate for your domain, one can configure Traefik to use it as the fallback/default for TLS connections.
Create The Dynamic Config File
First, we need to create a dynamic-config.yml
file that specifies the path to where the TLS certificates will be inside the container.
In this case, I am calling them wildcard.crt
for the certificate "bundle", and private.pem
for the private key.
tls:
stores:
default:
defaultCertificate:
certFile: /ssl/wildcard.crt
keyFile: /ssl/private.pem
Add File Provider To Static Config
Update the static-config.yml
file to add a "file provider" (which is our `dynamic-config.yml file).
# ...
providers:
docker:
endpoint: unix:///var/run/docker.sock
exposedByDefault: true
file:
directory: /etc/traefik/dynamic
Update Traefik Docker Compose
Now update the docker-compose.yml
file to:
- listen for port 443
- Provide the
dynamic-config.yml
dynamic configuration file through a read-only volume. - Provide the certificates through a read-only volume (in this case a folder called
ssl
at the same level as thedocker-compose.yml
file).
version: "3.9"
networks:
traefik-net:
external: true
services:
reverse-proxy:
container_name: traefik
image: traefik:v2.8
networks:
- traefik-net
ports:
- "80:80" # "web" HTTP listener
- "443:443" # "websecure" SSL listener
- "8080:8080" # Traefik dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Allows Traefik to listen to the Docker events
- ./static-config.yml:/etc/traefik/traefik.yml:ro # Provide the static config file.
- ./dynamic-config.yml:/etc/traefik/dynamic/conf.yml:ro # Provide the dynamic config file (SSL)
- ./ssl:/ssl:ro # Wildcard default SSL certificate referenced in dynamic-config.yml
Update Web Service Labels
Finally, we need to update the labels
on the web services we deploy, to specify the routing for TLS connections on the websecure
endpoint.
version: "3.9"
networks:
traefik-net:
external: true
services:
whoami:
container_name: whoami
image: traefik/whoami
networks:
- traefik-net
labels:
# Specify http routing
- traefik.http.routers.whoamihttp.entrypoints=web
- traefik.http.routers.whoamihttp.rule=Host("whoami1.programster.org")
- traefik.http.routers.whoamihttp.tls=false
# now specify routing for https
- traefik.http.routers.whoami.entrypoints=websecure
- traefik.http.routers.whoami.rule=Host("whoami1.programster.org")
- traefik.http.routers.whoami.tls=true
Redirecting HTTP to HTTPS
If you would like to redirect HTTP connections to HTTPS on a per-service basis (e.g. not configure Traefik to do this globally for all connections), then one can just update the service's labels to add a middleware to perform this routing on the HTTP endpoint.
version: "3.9"
networks:
traefik-net:
external: true
services:
whoami:
container_name: whoami
image: traefik/whoami
networks:
- traefik-net
labels:
# Specify http routing
- traefik.http.routers.whoamihttp.entrypoints=web
- traefik.http.routers.whoamihttp.rule=Host("whoami1.programster.org")
- traefik.http.routers.whoamihttp.tls=false
# Add middleware to redirect http to https on port 443
- traefik.http.middlewares.redirect-web-secure.redirectscheme.scheme=https
- traefik.http.routers.whoamihttp.middlewares=redirect-web-secure
# now specify routing for https
- traefik.http.routers.whoami.entrypoints=websecure
- traefik.http.routers.whoami.rule=Host("whoami1.programster.org")
- traefik.http.routers.whoami.tls=true
It is the two lines under # Add middleware to redirect http to https on port 443
that are relevant to this section.
On the first like, we create a middleware called redirect-web-secure
, which is set to change the scheme to https
.
On the second line, we register the middleware against the whoamihttp
router, (which listens on the web
entrypoint).
Exposed By Default
In the configurations above, I had exposedByDefault
set to true in the static configuration file, like so:
# ...
providers:
docker:
endpoint: unix:///var/run/docker.sock
exposedByDefault: true
file:
directory: /etc/traefik/dynamic
This will mean that all containers run on the host will be exposed by Traefik, by default, meaning that it will create routes for all detected containers. You may (likely) not wish for this to be the case. Thus I would recommend setting this to false like so:
# ...
providers:
docker:
endpoint: unix:///var/run/docker.sock
exposedByDefault: false
file:
directory: /etc/traefik/dynamic
... but now for all the services that you do wish to be exposed through Traefik, you need to add the traefik.enable=true
label them, to tell Traefik to go ahead and let them be exposed.
This can be done in the docker-compose configuration like so:
services:
app:
labels:
- traefik.enable=true
References
- doc.traefik.io - Traefik & Docker
- traefik.io - Traefik Proxy 2.x and TLS 101
- Stack Overflow - How to redirect http to https with Traefik 2.0 and Docker Compose labels?
First published: 2nd September 2022