Blogs
Introduction to Docker Swarm (Part 2): Integrating Traefik

Docker

Introduction to Docker Swarm (Part 2): Integrating Traefik

#docker

Technology, Published On : 4 March 2024
Introduction to Docker Swarm-2

This is part 2 of a 3-part blog series looking at Docker Swarm. We will be picking up from where we left off in the previous article. In the previous article, we were able to run our application using Docker Swarm, but we weren’t able to use our application. We need to add a load balancer to make it work. In production, we will be running multiple replicas of a single service to handle the load. Hence it is important to integrate a load balancer into the cluster so that the incoming requests are distributed between the replicas. In this article, we will add the Traefik load balancer for redirecting requests to our service.

Prerequisites:

Since we are picking from where we left off in the previous article, we are assuming that you can run Docker swarm. Please check this Github repo in case you haven’t set up the project.

1. Adding the Traefik service

We need to add a load balancer or web server to redirect the incoming requests to the service. Some of the popular options are Nginx and Traefik. In this article, we will be using Traefik.

Traefik is an open-source load balancer and reverse proxy. The following are some of the features of Traefik:

  • Traefik configuration can be implemented through static configuration, dynamic configuration, or a combination of both.
  • It allows us to redirect requests based on the domain, pathname, path prefix, host header, etc.
  • It has built-in support for Let’s Encrypt integration
  • It allows us to configure sticky sessions

In this article, we will be using both static and dynamic configurations.

Let’s add a new service to our docker-compose.yml file called Traefik to integrate Traefik into the stack. Paste the following under the services section.

traefik:
 image: traefik:v2.10.7
 deploy:
     mode: global
 networks:
   - sample-net
 ports:
   - target: 80
     published: 3000
     protocol: tcp
     mode: host
 volumes:
   - ./traefik.yml:/etc/traefik/traefik.yml
   - "/var/run/docker.sock:/var/run/docker.sock:ro"

Let’s go through the service:

image: traefik:v2.10.7

We are using the image of Traefik.

deploy:
    mode: global

This will instruct docker to deploy it globally so that even if we have multiple nodes, the Traefik service can redirect requests across multiple nodes in the cluster.

networks:
 — sample-net

We are instructing docker to deploy the service in a network called sample-net.

ports:
 — target: 80
 published: 3000
 protocol: tcp
 mode: host

We instruct Docker to listen to port 3000 in the host machine (Meaning port 3000 is exposed to access this service). All incoming requests from port 3000 from outside the container will be redirected to port 80 inside the docker container. Then we have mentioned the protocol and the mode.

volumes:
 — ./traefik.yml:/etc/traefik/traefik.yml
 — “/var/run/docker.sock:/var/run/docker.sock:ro”

Under volumes, we are loading the static configurations (We will add the static configuration next) into the container and listening to docker events for dynamic configurations.

2. Adding the static configuration for Traefik

The static configuration will be used when the Traefik service starts. Create a new file called traefik.yml and paste the following code into it:

providers:
 docker:
   swarmMode: true
   network: sample-net
   exposedbydefault: false

log:
 level: DEBUG

entryPoints:
 web:
   address: :80
providers:
 docker:
 swarmMode: true
 network: sample-net
 exposedbydefault: false

Since we are using docker we need to specify the configuration under the docker section. We need to enable swarm mode and specify the docker network. exposedbydefault: false tells Traefik to listen for dynamic configurations

log:
 level: DEBUG

This will enable logs in Traefik.

entryPoints:
 web:
 address: :80

EntryPoints are the network entry points into Traefik. They define the port that will receive the packets.

3. Adding the Dynamic configuration for Traefik

The dynamic configuration for Traefik can be added under the labels, or commands section of the service defined in the docker-compose.yml file. We need to redirect requests from Traefik to our nodeapp service, hence we will add it under it. Paste the following code under the deploy section of the nodeapp service.

labels:
 - "traefik.enable=true"
 - "traefik.http.routers.api-redirect.service=nodeapp-service"
 - "traefik.http.routers.api-redirect.entryPoints=web"
 - "traefik.http.routers.api-redirect.rule=PathPrefix(`/`)"
 -"traefik.http.services.nodeapp-service.loadBalancer.server.port=3000"

Let’s go through the above configuration:

traefik.enable=true

We have enabled Traefik for this service.

t-traefik.http.routers.api-redirect.service=nodeapp-service

Then we are adding our custom route called api-redirect under http.routes section. We are instructing Traefik to redirect incoming requests to a Traefik service called nodeapp-service. The important point to note here is Traefik service is different from the services (nodeapp is a service) that we mention in the docker-compose.yml file.

traefik.http.routers.api-redirect.entryPoints=web

We have mentioned the EntryPoint as web which is listening to port 80.

traefik.http.routers.api-redirect.rule=PathPrefix(`/`)

This is the rule through which Traefik will redirect incoming requests. Since nodeapp is the only service we have in our stack we are telling Traefik to send all requests to this service. PathPrefix, as the name says is a rule for filtering requests that starts with a certain pathname.

traefik.http.services.nodeapp-service.loadBalancer.server.port=3000

Under the services section, we have a service called nodeapp-service . Under this service, we have specified the port number to redirect the incoming request to. This will connect with the nodeapp which running in port 3000.

There are other ways to add the dynamic configurations you can check the Traefik documentation for more details. The final docker-compose.yml file will look like the following:

version: "3.9"

services:

 traefik:
   image: traefik:v2.10.7
   deploy:
       mode: global
   networks:
     - sample-net
   ports:
     - target: 80
       published: 3000
       protocol: tcp
       mode: host
   volumes:
     - ./traefik.yml:/etc/traefik/traefik.yml
     - "/var/run/docker.sock:/var/run/docker.sock:ro"

 nodeapp:
   image: 127.0.0.1:5000/nodeapp
   networks:        # <-------- add 'sample-net' network
     - sample-net
   deploy:
     replicas: 1
     restart_policy:
       condition: any
     update_config:
       parallelism: 1
       delay: 15s
     labels:
       - "traefik.enable=true"
       - "traefik.http.routers.api-redirect.service=nodeapp-service"
       - "traefik.http.routers.api-redirect.entryPoints=web"
       - "traefik.http.routers.api-redirect.rule=PathPrefix(`/`)"
       - "traefik.http.services.nodeapp-service.loadBalancer.server.port=3000"
   build:
     context: .
     args:
       NODE_ENV: production
   command: ["npm", "run", "start"]

networks:         # <-------- initialize the network
 sample-net:

Notice that we have removed the ports section from the nodeapp service.

networks:
 — sample-net

We have added nodeapp to the same network where Traefik is running so that they can communicate.

networks:
 sample-net:

At the bottom of the file, we have initialized sample-net under the network section.

After enabling Docker swarm mode (We did this in the previous article), we can deploy the stack once again with the Traefik service using the following command:

$ docker stack deploy -c docker-compose.yml node_stack
Ignoring unsupported options: build

Creating network node_stack_sample-net
Creating service node_stack_traefik
Creating service node_stack_nodeapp

You will notice the Traefik service is also running now. If you access. nodeapp in your browser, it should work the same as before. The text “Hello world!” will be visible.

Cheers! you have successfully deployed your NodeJS app using the Traefik load balancer. To see the deployment logs in the Traefik service you can use the following command:

docker logs

In the next article, we will learn how to Scale our application, perform rolling updates, and more.

You can refer to the entire source code for this article in this GitHub repo.

Dinesh

Dinesh Murali

Lead-Technology

Software engineer by job and adventure seeker by nature. I thrive on developing awesome applications. When not working, I love being in nature and exploring the great outdoors.

Let’s collaborate

Need assistance or have questions?

Want cutting-edge solutions minus the headaches? Contact us to shape your digital future.

Modal img

Discover Next-Generation AI Solutions for Your Business!

Let's collaborate to turn your business challenges into AI-powered success stories.

Get Started