Blog

A basic introduction to Traefik

Andrey Velikov
Andrey Velikov
DevOps and Cloud Engineer
14.06.2023
Reading time: 7 mins.
Last Updated: 01.11.2023

Table of Contents

Prerequisites: Docker knowledge

1. What is Traefik?

Traefik is an open-source solution serving as a reverse proxy and load balancing for services. What makes it stand out is its possibility for dynamic routing.

2. Why use Traefik?

Traefik uses dynamic routing to target services without any manual intervention which makes it very convenient, if you need simple and fast implementation of a solution for your microservices for example. In comparison with other reverse proxy solutions where you need to manually update the configuration (which might be tedious and time-consuming), now Traefik detects these changes automatically and activates them.  

3. How does Traefik work?

Since we explained the basic concept of Traefik, now we can proceed with understanding how it works. First, we need to get familiar with its components and the configuration.

The automatic configuration discovery is achieved with the help of providers. The providers could be cloud providers, container engines, and other infrastructure components. Docker, Kubernetes, or Amazon ECS to name a few. Traefik works with dozens of them. In addition to the dynamic routing, you no longer need to maintain a configuration file. Instead, Traefik scans the entire infrastructure every 2 seconds (by default but this is editable) and reads the information you attach to the services. The labels in the Docker provider contain such information according to which Traefik routes the requests.

how does traefik work

Installation of Traefik and Basic demonstration

Let’s demonstrate how Traefik is routing requests dynamically. For this purpose, we are going to use the Docker provider.

First, we need to pull the required containers. (At the time of writing the latest version is v2.9)

docker pull traefik

Now before running the container, we need to include some options. We will use a docker-compose file and describe all the options required to run a basic working configuration of Traefik.

First, let us create a network for Traefik:

docker network create traefik-net

Next, we will write the compose file with the following options explained in a comment:

version: '3'

services:
  traefik:
    image: "traefik:v2.9"
    container_name: "traefik"
    ports:
      - "80:80"
      - "8080:8080" # Expose Dashboard
    command:
      - --providers.docker=true # Enables docker as the provider
      - --api.insecure=true # Allows using the api without any ssl certs
      - --api.dashboard=true # Allows dashboard to detect services (dashboard explained below)
      - --providers.docker.network=traefik-net # Traefik will be working in the network we created named “traefik-net”
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - traefik-net

networks:
  traefik-net:
    external: true

We are ready to run the container:

docker-compose up -d 

We can check the running container with the docker ps command

CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                                                          NAMES
144e6e1cbcd2   traefik:v2.9   "/entrypoint.sh --pr…"   19 minutes ago   Up 18 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   traefik

As you have probably noticed from the compose file, we already exposed the dashboard of Traefik. We can access it on port 8080:

traefik dashboard

Few words on the dashboard

The dashboard is a very convenient and pretty way to view the statistics of your services and routes. When a service gets scanned by Traefik, it will appear automatically on the dashboard. If we go to the HTTP section, we can see that we already have 3 routers. According to the official documentation, a router is in charge of connecting incoming requests to the services that can handle them. The port 80, which is one of the entrypoints, is reserved for the incoming requests.

routers

The routers we see here are the default ones that define the routes to the Traefik components. 

Note: The dashboard can be very convenient, as we noted. However, it is a security liability and shouldn’t be exposed in an environment that has outside network access. Therefore, in a production environment it should be either disabled (remove port 8080 from the compose file), properly protected with SSL certificates and other means, or just used only in an internal network.

Adding services to Traefik

Let’s add a service to which Traefik will route the requests. For the sole purpose of this demonstration, we are going to use an Nginx web server in docker.

Directly pull the image and start the nginx container:

docker run -d -p 8081:80 –net=traefik-net nginx

Note that we are starting the container in the docker network we created earlier and exposed port 8081 for the webserver since port 80 is already used by Traefik to route through it any requests.

After we ensure that nginx is running we can check how it appears in the dashboard. And without any additional intervention, we can see the new Host:

host traefik

Now the new host is not a FQDN and we cannot access it that way, which means Traefik cannot route any requests through it at the moment. As we know Traefik scans the services and specifically looks for container labels. The labels serve as instructions for Traefik.

Let us add labels to the containers.

Run docker-compose down and edit the compose file as follows:

version: '3'

services:
  traefik:
    image: "traefik:v2.9"
    container_name: "traefik"
    ports:
      - "80:80"
      - "8080:8080" # Expose Dashboard
    command:
      - --providers.docker=true
      - --api.insecure=true
      - --api.dashboard=true
      - --providers.docker.network=traefik-net
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - traefik-net
    labels:
      - "traefik.enable=true" # Enable assigning subdomain to the dashboard
      - "traefik.http.routers.api.rule=Host(`traefik.localhost`)" # Domain for the dashboard

  nginx1:
    image: "nginx:latest"
    container_name: "nginx1"
    ports:
      - "8081:80"
    depends_on:
      - traefik
    networks:
      - traefik-net
    labels:
      - "traefik.http.routers.nginx1.rule=(Host(`nginx.localhost`)
      - "traefik.enable=true" # Enable assigning subdomain to the service
networks:
  traefik-net:
    external: true

traefik.http.routers.nginx1.rule will set the localhost from which Traefik will route the request to the webserver.

docker-compose up -d

We see that we now have a proper host. Let’s test if it works:

host traefik

Notice that now we can connect to the dashboard via the traefik.localhost domain which we set in the label of the container. The nginx.localhost should also redirect us to the webserver container:

welcome to nginx traefik

Configuring more than one service with a single domain 

The typical use case is when we have microservices that are using one domain. We are going to create two custom Nginx images with custom configs. Let’s pretend that those 2 containers will have different functions.

First webserver default.conf:

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;


    location  /static {
        alias   /usr/share/nginx/html/static;
        try_files $uri $uri/ @static;
        index index.html;
    }

    location @ static {
      rewrite /static/(.*)$ /static/index.html?/$1 last;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Dockerfile:

FROM nginx 

RUN mkdir -p /usr/share/nginx/html/static
COPY index.html /usr/share/nginx/html/static
RUN chmod -R 755 /usr/share/nginx/html/static
COPY default.conf /etc/nginx/conf.d

Create a custom index file. The contents of mine are just “STATIC PAGE”.

Second web server default.conf:

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;


    location  /info {
        alias   /usr/share/nginx/html/info;
        try_files $uri $uri/ @info;
        index index.html;
    }

    location @ info {
      rewrite /info/(.*)$ /info/index.html?/$1 last;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Dockerfile:

FROM nginx 

RUN mkdir -p /usr/share/nginx/html/static
COPY index.html /usr/share/nginx/html/static
RUN chmod -R 755 /usr/share/nginx/html/static
COPY default.conf /etc/nginx/conf.d

Create the second index file with a different content.

Build both of the images in the respective directories. I will call them nginx1 and nginx2.

docker build -t nginx1 .
docker build -t nginx2 .

Update the compose file and add the labels to the new containers with the proper rules.

version: '3'

services:
  traefik:
    image: "traefik:v2.9"
    container_name: "traefik"
    ports:
      - "80:80"
      - "8080:8080" # Expose Dashboard
    command:
      - --providers.docker=true
      - --api.insecure=true
      - --api.dashboard=true
      - --providers.docker.network=traefik-net
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - traefik-net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`traefik.localhost`)"

  nginx1:
    image: "nginx1:latest"
    container_name: "nginx1"
    ports:
      - "8081:80"
    depends_on:
      - traefik
    networks:
      - traefik-net
    labels:
      - "traefik.http.routers.nginx1.rule=(Host(`nginx.localhost`) && PathPrefix(`/static`))"
      - "traefik.enable=true"

  nginx2:
    image: "nginx2:latest"
    container_name: "nginx2"
    ports:
      - "8082:80"
    depends_on:
      - traefik
    networks:
      - traefik-net
    labels:
      - "traefik.http.routers.nginx2.rule=(Host(`nginx.localhost`) && PathPrefix(`/info`))"
      - "traefik.enable=true"

networks:
  traefik-net:
    external: true

PathPrefix rule matches the request prefix path. 

Start the containers:

sudo docker-compose up -d

On the dashboard now we can see both of the Hosts.

traefik

Let’s see if we have access to each of the URLs:

static page traefik
information page traefik

Traefik successfully redirects the requests according to the URL based on the labels we set in the containers. This is how you can set dynamic and automatic routing to your microservices. 

Conclusion

In this guide, we demonstrated that with a straightforward configuration, Traefik can be of great practical use. In addition, its capabilities are not at all limited to those we have presented. Traefik offers many more advanced options, such as adding HTTP middleware, additional rules, SSL certificates to the services, and more. There are also a lot more cases in which Traefik can be of help. Feel free to dive deeper and explore new case scenarios and learn more about how to simplify your work with this modern reverse proxy!

2 Responses

  1. Very nice article. Can you please help understanding if we need to horizontally scale traefik then what should be the approach?

    1. Hi Sanjeev,

      You can run multiple traefik instances. So, you should look for a solution with docker swarm mode.

Leave a Reply

Your email address will not be published. Required fields are marked *

More Posts

In the dynamic world of serverless computing, securing your AWS Lambda function is crucial. However, one often neglected area is the security of containerized applications in Amazon Elastic Container Registry...
Reading
Note: The following example demonstrates upgrading a Kubernetes cluster from version 1.23 to 1.24. Replace the version numbers according to your specific setup. To ensure a seamless upgrade, it’s crucial...
Reading
Get In Touch
ITGix provides you with expert consultancy and tailored DevOps services to accelerate your business growth.
Newsletter for
Tech Experts
Join 12,000+ business leaders and engineers who receive blogs, e-Books, and case studies on emerging technology.