Hi, so I am not sure if I am being dense but I can't seem to get traefik working on my swarm. I have 1 manager and 3 workers.
If I attach the labels to the containers and run them only on the manager it'll work no problems, but if I add them to the services and run them on my workers, no mas don't wanna work.
Am I just missing something obvious?
version: '3.8'
services:
traefik:
# Use the latest Traefik image
image: traefik:latest
ports:
# Listen on port 80, default for HTTP, necessary to redirect to HTTPS
- target: 80
published: 80
mode: host
# Listen on port 443, default for HTTPS
- target: 443
published: 443
mode: host
deploy:
placement:
constraints:
- node.role == manager
labels:
# Enable Traefik for this service, to make it available in the public network
- traefik.enable=true
# Use the traefik-public network (declared below)
- traefik.docker.network=traefik-public
# Use the custom label "traefik.constraint-label=traefik-public"
# This public Traefik will only use services with this label
# That way you can add other internal Traefik instances per stack if needed
- traefik.constraint-label=traefik-public
# admin-auth middleware with HTTP Basic auth
# Using the environment variables USERNAME and HASHED_PASSWORD
- traefik.http.middlewares.admin-auth.basicauth.users=${USERNAME?Variable not set}:${HASHED_PASSWORD?Variable not set}
# https-redirect middleware to redirect HTTP to HTTPS
# It can be re-used by other stacks in other Docker Compose files
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.https-redirect.redirectscheme.permanent=true
# traefik-http set up only to use the middleware to redirect to https
- traefik.http.routers.traefik-public-http.rule=Host(`traefik.example.com`)
- traefik.http.routers.traefik-public-http.entrypoints=http
- traefik.http.routers.traefik-public-http.middlewares=https-redirect
# traefik-https the actual router using HTTPS
- traefik.http.routers.traefik-public-https.rule=Host(`traefik.example.com`)
- traefik.http.routers.traefik-public-https.entrypoints=https
- traefik.http.routers.traefik-public-https.tls=true
# Use the special Traefik service api@internal with the web UI/Dashboard
- traefik.http.routers.traefik-public-https.service=api@internal
# Enable HTTP Basic auth, using the middleware created above
- traefik.http.routers.traefik-public-https.middlewares=admin-auth
# Define the port inside of the Docker service to use
- traefik.http.services.traefik-public.loadbalancer.server.port=8080
# Certs
- "traefik.http.routers.proxy-https.tls.domains[0].main=.example.com"
- "traefik.http.routers.proxy-https.tls.domains[0].sans=*.example.com"
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /mnt/data/docker/data/traefik/data/traefik.yml:/traefik.yml:ro
- /mnt/data/docker/data/traefik/data/acme.json:/acme.json
#- /mnt/data/docker/data/traefik/data/config.yml:/config.yml:ro
command:
# Enable Docker in Traefik, so that it reads labels from Docker services
- --providers.docker
# Add a constraint to only use services with the label "traefik.constraint-label=traefik-public"
- --providers.docker.constraints=Label(`traefik.constraint-label`, `traefik-public`)
# Do not expose all Docker services, only the ones explicitly exposed
- --providers.docker.exposedbydefault=false
# Enable Docker Swarm mode
- --providers.docker.swarmMode=true
# Create an entrypoint "http" listening on address 80
- --entrypoints.http.address=:80
# Create an entrypoint "https" listening on address 443
- --entrypoints.https.address=:443
# Enable the access log, with HTTP requests
- --accesslog
# Enable the Traefik log, for configurations and errors
- --log
# Enable the Dashboard and API
- --api
environment:
- CF_API_EMAIL=xxxxxx@gmail.com
#- CF_DNS_API_TOKEN=YOU_API_TOKEN
- CF_API_KEY=xxxxxx
# be sure to use the correct one depending on if you are using a token or key
networks:
# Use the public network created to be shared between Traefik and
# any other service that needs to be publicly available with HTTPS
- traefik-public
networks:
traefik-public:
driver: overlay
attachable: true
name: traefik-public
Been here, feel the pain. Love swarm/traefik for home lab. Hopefully one of the admins chimes in soon, but I was looking for something else and noticed this post.
- "#certs" labels define tls configs for a router that appears not to have any service defined
- I believe updated docs point at defining permanent redirects under the entrypoint(s), not as middlewares.
- use of bind mounts instead of named volumes
Caveat to all of it -- I can't explain how/why, but have done all the aforementioned and not had per se issues until adding other/more services later. I'm redoing my entire setup because it led to issues. Summary point -- DockerSwarmRocks is outdated, and is a good way to get caught 95 percent there without a chance at getting to 100 percent.
1 Like
In the command portion of your traefik remove the - --providers.docker
leaving only the providers.docker.swarmMode line. I think they are supposed to be mutually exclusive.
traefik:
image: docker-dev-artifactory.workday.com/traefik:2.4.9
command:
- --providers.docker.swarmMode=true
Insure your labels are declared under the deploy section. It appears that you have done this but pointing it out for others at a later date that may not have noticed this requirement.
deploy:
labels:
# routes for traefik itself
- traefik.enable=true
- traefik.http.services.traefik.loadbalancer.server.port=8080
Note that deploy
is at the same level as command
above.
Docker itself can only "see" container labels on its own host. If you want to examine labels across hosts, you need to associate them with the service. The Swarm plumbing is what enables the communication between hosts within the cluster.
My guess is that the first providers.docker
declaration took precedence. Given it will only be a one line change to test it, it is worth a shot.
Cheers, gave it a go and even moved command to just below image and no mas
I know this is an older post, but I am having a similar problem and wondering if you ever determined how to fix it?
This example assumes you only have a single manager node, otherwise LetsEncrypt certificate validation will not work. Use with docker stack deploy
.
version: '3'
services:
traefik:
image: traefik:v2.10
hostname: '{{.Node.Hostname}}'
ports:
# listen on host ports without ingress network
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
networks:
- proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /var/log:/var/log
- letsencrypt:/letsencrypt
deploy:
mode: global
placement:
constraints:
- node.role==manager
labels:
- traefik.enable=true
- traefik.http.routers.mydashboard.rule=Host(`traefik.example.com`)
- traefik.http.routers.mydashboard.service=api@internal
- traefik.http.routers.mydashboard.middlewares=myauth
- traefik.http.services.mydashboard.loadbalancer.server.port=1337
- traefik.http.middlewares.myauth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/
command:
- --api.dashboard=true
- --log.level=INFO
#- --log.filepath=/var/log/traefik.log
- --accesslog=true
#- --accesslog.filepath=/var/log/traefik-access.log
- --providers.docker.exposedByDefault=false
- --providers.docker.network=proxy
- --providers.docker.swarmMode=true
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entryPoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
- --entrypoints.websecure.http.tls.certresolver=myresolver
- --certificatesresolvers.myresolver.acme.email=mail@example.com
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.myresolver.acme.tlschallenge=true
whoami:
image: traefik/whoami:v1.10
hostname: '{{.Node.Hostname}}'
networks:
- proxy
deploy:
mode: global
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.whoami.rule=Host(`whoami.example.com`) || PathPrefix(`/whoami`)'
- 'traefik.http.services.whoami.loadbalancer.server.port=80'
networks:
proxy:
name: proxy
driver: overlay
attachable: true
volumes:
letsencrypt:
name: letsencrypt
1 Like
Hi, I'm getting 404 when accessing the traefik dashboard and services on their respected domains? Is there something I'm missing.
version: "3.7"
services:
traefik:
image: "traefik:3.1"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--api.insecure=false"
- "--api.dashboard=true"
- "--accesslog=true"
- "--accesslog.filepath=/var/logs/access.log"
- "--providers.docker=true"
- "--providers.swarm.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.myhttpchallenge.acme.email=admin@safle.com"
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
deploy:
mode: global
placement:
constraints:
- node.role==manager
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik-secure.entrypoints=websecure"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=myhttpchallenge"
- "traefik.http.routers.traefik-secure.rule=Host(`devops-monitor.example.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=user:MlkmiPKTl0OB7BAS"
- "traefik.http.routers.traefik-secure.service=api@internal"
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:[a-z-.]+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.security-headers.headers.frameDeny=true"
- "traefik.http.middlewares.security-headers.headers.sslRedirect=true"
- "traefik.http.middlewares.security-headers.headers.STSIncludeSubdomains=true"
- "traefik.http.middlewares.security-headers.headers.STSPreload=true"
- "traefik.http.middlewares.security-headers.headers.STSSeconds=31536000"
- "traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security-headers.headers.browserXSSFilter=true"
- "traefik.http.middlewares.security-headers.headers.forceSTSHeader=true"
- "traefik.http.middlewares.rate-limit.ratelimit.period=5m"
- "traefik.http.middlewares.rate-limit.ratelimit.average=10"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=5"
- "traefik.http.middlewares.rate-limit.ratelimit.sourcecriterion.ipstrategy.depth=0"
ports:
- "80:80"
- "8080:8080"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./letsencrypt:/letsencrypt"
webapp-devops:
image: "image:latest"
container_name: devops
restart: always
deploy:
replicas: 2
labels:
- "traefik.enable=true"
- "traefik.http.routers.devops.rule=Host(`devops.example.com`)"
- "traefik.http.routers.devops.entrypoints=websecure"
- "traefik.http.routers.devops.tls=true"
- "traefik.http.routers.devops.tls.certresolver=myhttpchallenge"
- "traefik.http.routers.devops.middlewares=security-headers@docker,rate-limit@docker"
You probably shouldn't mix providers.docker
and providers.swarm
. From Traefik v3.x all Swarm functionality of providers.docker
was moved to providers.swarm
.
Ports are opened, entrypoints
are defined. You have a traefik.yml
file in use?
You run a full Swarm with multiple nodes? Does your domain DNS point to the right node?
Maybe compare to simple Traefik Swarm example. Note that regular LetsEncrypt only works with a single Traefik instance, only Traefik EE supports clustered LE.
1 Like
No I am not using any static config like traefik.yml.
No I am running the docker swarm on a single node only, also when I try to add another node in docker swarm the load doesn't get distributed to the other node for some reason.
My domain DNS points to the manager node.
But thank you so much for the reply, let me try with your example yml and change my configs accordingly.
Will give you an update if this actually worked for me or not.
I updated my configs according to your sample yml provided and downgraded the traefik version to 2.10 since the latest 3.x versions doesn't support swarm flag but am still getting the same 404 error, what do you think why is this happening?
version: "3.7"
services:
traefik:
image: "traefik:2.10"
container_name: "traefik"
command:
- "--log.level=DEBUG"
- "--api.insecure=false"
- "--api.dashboard=true"
- "--accesslog=true"
- "--providers.docker.swarmMode=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"
- "--entrypoints.websecure.http.tls.certresolver=namecheap"
- "--certificatesresolvers.myhttpchallenge.acme.email=admin@safle.com"
- "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
deploy:
mode: global
placement:
constraints:
- node.role==manager
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik-secure.entrypoints=websecure"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=myhttpchallenge"
- "traefik.http.routers.traefik-secure.rule=Host(`monitor.example.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=user:M0xOo5OVnaB3JMlkmiPKTl0OB7BAS"
- "traefik.http.routers.traefik-secure.service=api@internal"
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:[a-z-.]+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.security-headers.headers.frameDeny=true"
- "traefik.http.middlewares.security-headers.headers.sslRedirect=true"
- "traefik.http.middlewares.security-headers.headers.STSIncludeSubdomains=true"
- "traefik.http.middlewares.security-headers.headers.STSPreload=true"
- "traefik.http.middlewares.security-headers.headers.STSSeconds=31536000"
- "traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security-headers.headers.browserXSSFilter=true"
- "traefik.http.middlewares.security-headers.headers.forceSTSHeader=true"
- "traefik.http.middlewares.rate-limit.ratelimit.period=5m"
- "traefik.http.middlewares.rate-limit.ratelimit.average=10"
- "traefik.http.middlewares.rate-limit.ratelimit.burst=5"
- "traefik.http.middlewares.rate-limit.ratelimit.sourcecriterion.ipstrategy.depth=0"
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./letsencrypt:/letsencrypt"
- "/var/log:/var/log"
devops:
image: "image:latest"
container_name: "devops"
restart: always
deploy:
replicas: 5
labels:
- "traefik.enable=true"
- "traefik.http.routers.devops.rule=Host(`devops-example.com`)"
- "traefik.http.routers.devops.entrypoints=websecure"
- "traefik.http.routers.devops.tls=true"
- "traefik.http.routers.devops.tls.certresolver=myhttpchallenge"
- "traefik.http.routers.devops.middlewares=security-headers@docker,rate-limit@docker"
- "traefik.http.services.devops.loadbalancer.server.port=3001"