[SOLVED] Setup Docker Swarm + Traefik 2.4 + domain-based routing on bare metal with CLI?

I would like to scale my Docker webapp and make it highly available. I have been using Docker for many years and K8s seems overly complicated, therefore I am looking into Docker Swarm.

The idea is to have an external highly available load balancer as first contact, forwarding all TCP/IP traffic to 3 Docker Swarm master nodes with Traefik 2.4 listening directly on the servers port (0.0.0.0:80). Traefik uses the http domain configured in the service to forward it to an appropriate container on one of the workers over the Docker network.

For simplicity this is just plain http, not even that is working for me. The load balancer is configured correctly, the Docker Swarm is up and running. This is how I start the services:

sudo docker network create --driver=overlay traefik-public

# reverse proxy service
sudo docker service create \
  --name traefik \
  -p 80:80 \
  --mount type=bind,source=/var/run/docker.sock,destination=/var/run/docker.sock \
  --mode=global \
  --constraint node.role==manager \
  --network traefik-public \
  traefik:2.4 \
    --providers.docker.swarmMode=true \
    --providers.docker.endpoint=unix:///var/run/docker.sock \
    --providers.docker.exposedbydefault=false \
    --providers.docker.watch=true \
    --providers.docker.network=traefik-public \
    --entryPoints.web.address=:80
# webapp A service
sudo docker service create \
  --replicas 5 \
  --name hostname \
  --constraint node.role!=manager \
  --network traefik-public \
  --publish published=8080,target=80 \
  --label  traefik.enabled=true \
  --label 'traefik.http.routers.hostname.rule=Host(`a.domain.tld`)' \
  --label  traefik.http.routers.hostname.entrypoints=http \
  --label  traefik.http.services.hostname.loadbalancer.server.scheme=http \
  --label  traefik.http.services.hostname.loadbalancer.server.port=8080 \
  nginxdemos/hello

For some reason there seems to be an error in the configuration. I have been trying to tweak it, but I either get an empty response or 404 page not found when using curl . Latest error is level=error msg="Skip container : field not found, node: enabled" providerName=docker .

Assumptions:

  1. Traefik is running on Swarm master nodes to get Docker event notifications
  2. Traefik is listening directly on external port 80 of master nodes
  3. Traefik will recognize new services and route to containers based on domain name
  4. Multiple webapp container of the same service can run on the same worker node

Questions:

  1. How do I get the basic version up and running? Where is the mistake?
  2. How do I access Traefik dashboard? I assume every dashboard will show different data.
  3. How to add own SSL certificates to Traefik? Do Swarm services support local storage?
    (I am for easy solutions, happy to copy my .pem on all 3 nodes, once every year)

Otherwise I am interested in any kind of feedback about the planned architecture.

Thanks, bluepuma

1 Like

That was your clue, the label is traefik.enable

TraefikEE supports this clustered solution. Without that you would have 3 independent Traefiks.

Yes Swarm supports local storage in the form of a Volume. docker cp can be one way to get files in. Or bind mount a local copy and the volume with a utility container(bash) and copy them that way.

Did you know you can use a compose file for a stack deploy too?

Thanks @cakiwi.

I traveled the whole world wide web in search for a dead simple solution to run Traefik 2.4 in Docker Swarm, to no avail. Would you like to help out making this post the reference by providing a working example? This could even be a fantastic blog post: the easy way for developers: from container to scale with Traefik and Docker Swarm :smiley: It just needs 2 commands:

docker service create --name traefik ...
docker service create --name webapp ...

PS: I admit I like plain CLI commands better, probably because I want to start and update 50+ services programmatically. Plus I feel it's shorter and you can still move to compose later.

What I want to achieve:

  • Traefic to run on master nodes listening on port 80
  • Traefic to forward requests based on domain label to service's containers via Docker network
  • Optional: Traefik dashboard with auth
  • Optional: listen on port 443 and use purchased wildcard certificate

Traefik has a nice tutorial for Docker, but where is the one for Docker Swarm?

Slooowly getting there:

  • Traefik is listening on host 0.0.0.0:80
  • Traefik shares network "proxy" with the web-app containers
  • wget can access the web pages from inside the Traefik container
version: '3.8'
services:
    traefik:
        image: traefik:v2.4
        ports:
          - target: 80
            published: 80
            protocol: tcp
            mode: host
        command:
            - --providers.docker.swarmMode=true
            - --providers.docker.exposedByDefault=false
            - --providers.docker.network=proxy
            - --accesslog
            - --log.level=debug
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock:ro
        networks:
            - proxy
        deploy:
            mode: global
            placement:
                constraints:
                    - node.role == manager

networks:
    proxy:
        external: true
docker network create --driver=overlay proxy

docker stack deploy --compose-file traefik.yml traefik

docker service create \
  --replicas 6 \
  --name hostname \
  --constraint node.role!=manager \
  --network proxy \
  --label traefik.enable=true \
  --label 'traefik.http.routers.hostname.rule=Host(`lb.domain.tld`)' \
  --label  traefik.http.routers.hostname.entrypoints=web \
  --label  traefik.http.services.hostname.loadbalancer.server.scheme=http \
  --label  traefik.http.services.hostname.loadbalancer.server.port=80 \
  nginxdemos/hello

Configuration is received:

2021-05-20T21:51:14.956805457Z time="2021-05-20T21:51:14Z" level=debug msg="Configuration received from provider docker: {\"http\":{\"routers\":{\"hostname\":{\"entryPoints\":[\"web\"],\"service\":\"hostname\",\"rule\":\"Host(`lb.domain.tld`)\"}},\"services\":{\"hostname\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://10.0.6.39:80\"},{\"url\":\"http://10.0.6.42:80\"},{\"url\":\"http://10.0.6.41:80\"},{\"url\":\"http://10.0.6.37:80\"},{\"url\":\"http://10.0.6.40:80\"},{\"url\":\"http://10.0.6.38:80\"}],\"passHostHeader\":true}}}},\"tcp\":{},\"udp\":{}}" providerName=docker

Just an external web browser still gets "404 page not found", seems Traefik is not forwarding.

So here is the first most basic working template, just http:

traefik.yml:

version: '3.8'
services:
    traefik: 
        image: traefik:v2.4
        ports:
          - target: 80
            published: 80 
            protocol: tcp 
            mode: host 
        command: 
          - --providers.docker.swarmMode=true 
          - --providers.docker.exposedByDefault=false 
          - --providers.docker.network=proxy 
          - --entrypoints.web.address=:80 
          - --accesslog 
          - --log.level=debug 
        volumes: 
          - /var/run/docker.sock:/var/run/docker.sock:ro 
        networks: 
          - proxy 
        deploy: 
            mode: global 
            placement: 
                constraints: 
                  - node.role == manager 
networks: 
    proxy: 
        external: true

CLI commands:

# create network (just once)
docker network create --driver=overlay proxy

# start traefic via traefic.yml
docker stack deploy --compose-file traefik.yml traefik

# start a web-app with its domain name
docker service create \
  --replicas 6 \
  --name hostname \
  --constraint node.role!=manager \
  --network proxy \
  --label  traefik.enable=true \
  --label 'traefik.http.routers.traefik.rule=Host(`lb.domain.tld`)' \
  --label  traefik.http.services.hostname.loadbalancer.server.port=80 \
nginxdemos/hello

My next steps:

  1. SSL with a purchased certificate
  2. http to https redirect
  3. routing with domain + path
  4. traefik dashboard with auth
  5. docker-socket-proxy for security

Reddit was most helpul, discussion over there.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.