Install Traefik in Docker Swarm
by Thomas Urban
This tutorial is providing brief example for setting up traefik in a freshly established Docker Swarm. It closely follows official descriptions found in Traefik's documentation, but adopts those examples to work in a Docker Swarm.
Prerequisites
This tutorial applies to a Docker Swarm. It's installation usually consists of setting up Docker Engine on three or more servers, run docker swarm init
and docker swarm join-token manager
on one of the servers and whatever command is displayed by the latter on every other server.
Persistent Volumes
Traefik works just fine in such a basic swarm. And that's what this tutorial is about. However, some additional features such as automatic maintenance of TLS certificates fetched from Letsencrypt require access on a persistent filesystem. This applies to further services you might want to set up in your swarm.
In a Docker Swarm persistent filesystems require additional setup. One option is to establish a GlusterFS cluster for sharing part of either server's filesystem.
Encrypt Ingress Networking
This isn't required by Traefik, but you should always make sure to encrypt any overlay network to prevent unencrypted traffic between your services from being eavesdropped. This includes your swarm's ingress network as it is an overlay network and it isn't encrypted by default.
Encrypting overlay networks may be beneficial in case of encountering basic communication issues between your swarm's nodes for encrypted networks are established via TCP-based IPSec instead of UDP-based VXLAN.
Due to starting with a fresh swarm we assume there is no running service right now. Otherwise you'll need to stop it for fixing the ingress network, at least.
-
Remove the existing ingress network using
docker network rm ingress
and confirm the warning popping up.
-
Re-create the ingress network using
docker network create --ingress --driver overlay \ --opt encrypted ingress
As an option you might want to increase the possible size of ingress network by defining its subnet explicitly:
docker network create --ingress --driver overlay \ --opt encrypted --subnet 10.10.0.0./16 ingress
Expose Docker API the Safer Way
Following this example you should put your Docker API behind proxy to limit requests available to Traefik. Let's adopt it for use in a swarm.
-
Create a file socket-proxy.yml containing this:
version: "3.8" services: socket-proxy: image: tecnativa/docker-socket-proxy volumes: - /var/run/docker.sock:/var/run/docker.sock:ro environment: CONTAINERS: 1 NETWORKS: 1 SERVICES: 1 TASKS: 1 networks: cloud-socket-proxy: aliases: - socket-proxy networks: cloud-socket-proxy: external: true
Additional environment variables are set to enable access on /networks/*, /services/* and /tasks/* which is required when setting up Traefik in swarm mode.
-
This file declares to access some existing network, so let's create it:
docker network create --driver overlay --scope swarm \ --opt encrypted --attachable cloud-socket-proxy
This command is creating another overlay network. Its name is cloud-socket-proxy. The prefix cloud- is chosen here to serve as a kind of namespace grouping every network and stack related to commonly manage your swarm. The --attachable option may introduce a security risk, but on the other hand it as enabling you to have custom containers using this Docker API filter as well.
-
Start the stack described by file created before.
docker stack deploy -c socket-proxy.yml cloud-socket-proxy
Install Traefik
Now it's time for setting up Traefik in its most basic way.
-
Start with creating file edge.yml defining your Traefik-based reverse proxy in a swarm-compliant way:
version: "3.8" services: reverse-proxy: image: traefik:v2.1 deploy: placement: constraints: - node.role == manager ports: - "80:80" - "443:443" - "8080:8080" networks: - cloud-edge - cloud-socket-proxy configs: - source: traefik target: /etc/traefik/traefik.yaml configs: traefik: file: ./traefik.yml networks: cloud-edge: external: true cloud-socket-proxy: external: true
This stack is attached to the cloud-socket-proxy network for accessing the Docker API via filtered TCP socket.
-
There is another network named cloud-edge which is assumed to exist prior to starting the stack defined before:
docker network create --driver overlay --scope swarm \ --opt encrypted --attachable --subnet 10.20.0.0/16 \ cloud-edge
This network is meant to have all the containers and services attached which are exposed for public access via Traefik. It is managed externally so other stacks in your swarm can attach to it as well.
-
Next create a static configuration file for Traefik named traefik.yml with this content:
api: insecure: true dashboard: true debug: false entryPoints: http: address: ":80" https: address: ":443" providers: docker: endpoint: "tcp://socket-proxy:2375" swarmMode: true watch: true exposedByDefault: false network: cloud-edge
By using a Docker configuration this file is implicitly exposed to any service container of reverse proxy as /etc/traefik/traefik.yaml. Whenever you adjust this file the stack started next must be restarted by tearing it down before re-starting again.
-
Now, start this stack:
docker stack deploy -c edge.yml cloud-edge
Check it out!
Open your favourite browser to visit http://node.of.your.swarm:8080. Replace node.of.your.swarm with hostname referring to any node of your swarm. Using either node's IP address is fine here, as well.
Now create another file test.yml containing
version: "3.8"
services:
whoami:
image: containous/whoami
deploy:
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`foo.example.com`)"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
networks:
- cloud-edge
networks:
cloud-edge:
external: true
Replace foo.example.com with name you've set up in DNS to refer to either node of your swarm. Start it with command
docker stack deploy -c test.yml test
It takes a few moments but eventually you can see the new route in dashboard URL provided before. In addition, when accessing http.//foo.example.com/ the service is invoked to show some information on your actual HTTP request.
Your Next Steps
- Set up TLS encryption with LetsEncrypt.
- Switch dashboard from insecure to secure mode.
- Add some actual service exposed via your new edge router.
Troubleshooting
If something does not work you should start checking the logs of either service created before.
docker service logs -f cloud-socket-proxy_socket-proxy
This is showing the log of socket proxy which is probably listing failed requests by Traefik.
docker service logs -f cloud-edge_reverse-proxy
This command is showing the log of Traefik and it might also show errors regarding communication with Docker API. In addition it should log discovered services.