Published on

Setting up docker swarm with traefik and portainer

4 min read

Posts in the Series

Part 1. Setting up Ubuntu Server with docker in Hetzner

Part 2. Setting up docker swarm with traefik and portainer (this post)

Part 3. Deploy redis, rabbitmq, seq, registry and postgres in docker swarm

Part 4. Deploy the microservice in docker swarm

Table of Contents

Intro

In this post we will see how to create a docker swarm and deploy traefik and portainer in our ubuntu server.

What is traefik?

Traefik is a leading modern reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your existing infrastructure components and configures itself automatically and dynamically.

For more info visit : https://traefik.io/traefik

What is portainer?

Portainer is the definitive container management tool for Docker, Docker Swarm with it's highly intuitive GUI and API. Portainer is a fully featured management tool for Docker. It runs locally, giving developers a rich UI to build and publish container images, deploy and manage applications and leverage data persistence and horizontal scaling for their applications. And, once an application is deployed into a container, Portainer makes it easy for users to secure, monitor and measure the performance of the platform. The tool negates the need for developers to learn Infrastructure as Code and makes it easy for them to maximize their efficiency which means both users and organizations love it.

For more info visit: https://www.portainer.io/

What is Docker Swarm?

Docker swarm is a container orchestration tool, meaning that it allows the user to manage multiple containers deployed across multiple host machines. One of the key benefits associated with the operation of a docker swarm is the high level of availability offered for applications.

For more info: https://docs.docker.com/engine/swarm/

Init Docker Swarm

docker swarm init --advertise-addr 10.0.0.3 # change the ip here with your machine ip

This will initialize docker in swarm mode and also display a join token for the other machines to join the cluster.

Create a traefik network

docker network create --driver overlay traefik-public

This is our primary network for the traefik.

Create a htpasswd password

docker run --rm httpd:2.4-alpine htpasswd -nbB admin <password> | cut -d ":" -f 2

Escape the signinthepasswordbyaddingonemoresign in the password by adding one more to the generated password. We need this password to protect our end point in the traefik proxy.

Create folders

for Traefik

create a folder and set 600 as permission.

mkdir /mnt/data
mkdir /mnt/data/traefik
touch /mnt/data/traefik/acme.json
chmod 600 /mnt/data/traefik/acme.json

for Portainer

mkdir /mnt/data/portainer

Traefik docker compose

Traefik is our main reverse proxy and it will sit in front of all out application. we will control all the routes to our containers using traefik.

version: '3.3'

services:
  traefik:
    image: 'traefik:v2.1.4'
    command:
      - --log.level=INFO
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --providers.docker
      - --providers.docker.exposedbydefault=false
      - --providers.docker.swarmmode=true
      - --providers.docker.network=traefik-public
      - --api
      - --api.dashboard=true
      - --certificatesresolvers.leresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
      # update your email here
      - --certificatesresolvers.leresolver.acme.email=youremail@test.com
      # Make sure the this file is available and permission is set correctly
      - --certificatesresolvers.leresolver.acme.storage=/le/acme.json
      - --certificatesresolvers.leresolver.acme.tlschallenge=true
    ports:
      - '80:80'
      - '443:443'
    networks:
      - traefik-public
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock:ro'
      # Make sure the volume folder is created
      - '/mnt/data/traefik/acme.json:/le/acme.json'
    deploy:
      labels:
        # Dashboard
        - 'traefik.enable=true'
        # Change the host url here
        - 'traefik.http.routers.traefik.rule=Host(`traefik.example.com`)'
        - 'traefik.http.routers.traefik.service=api@internal'
        - 'traefik.http.services.traefik.loadbalancer.server.port=8080'
        - 'traefik.http.routers.traefik.tls.certresolver=leresolver'
        - 'traefik.http.routers.traefik.entrypoints=websecure'
        - 'traefik.http.routers.traefik.middlewares=authtraefik'
        # Change the auth password here
        - 'traefik.http.middlewares.authtraefik.basicauth.users=admin:yournewpassword' # user/password

        # global redirect to https
        - 'traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)'
        - 'traefik.http.routers.http-catchall.entrypoints=web'
        - 'traefik.http.routers.http-catchall.middlewares=redirect-to-https'

        # middleware redirect
        - 'traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https'

  my-app:
    image: containous/whoami:v1.3.0
    networks:
      - traefik-public
    command:
      - --port=8082 # Our service listens on 8082
    deploy:
      labels:
        - 'traefik.enable=true'
        # Change the host url here
        - 'traefik.http.routers.my-app.rule=Host(`whoami.example.com`)'
        - 'traefik.http.services.my-app.loadbalancer.server.port=8082'
        - 'traefik.http.routers.my-app.middlewares=auth'
        - 'traefik.http.routers.my-app.entrypoints=websecure'
        - 'traefik.http.routers.my-app.tls=true'
        - 'traefik.http.routers.my-app.tls.certresolver=leresolver'
        # Change the password here
        - 'traefik.http.middlewares.auth.basicauth.users=admin:changeme' # user/password

networks:
  traefik-public:
    external: true

Portainer

Portainer is our container management software. We will use to deploy our docker containers.

version: '3.2'

services:
  agent:
    image: portainer/agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
    networks:
      - traefik-public
    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

  portainer:
    image: portainer/portainer
    command: -H tcp://tasks.agent:9001 --tlsskipverify
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      # make sure the folder is available
      - /mnt/volume2/portainer:/data
    networks:
      - traefik-public
    deploy:
      labels:
        - 'traefik.enable=true'
        # change the host here
        - 'traefik.http.routers.portainer.rule=Host(`admin.example.com`)'
        - 'traefik.http.services.portainer.loadbalancer.server.port=9000'
        - 'traefik.http.routers.portainer.entrypoints=websecure'
        - 'traefik.http.routers.portainer.tls=true'
        - 'traefik.http.routers.portainer.tls.certresolver=leresolver'
      mode: replicated
      placement:
        constraints: [node.role == manager]

networks:
  traefik-public:
    external: true