Traefik in Docker Swarm always gets 404

Hey Guys,

i've got a problem with Traefik 2.x in Docker Swarm :(.

First of all (and for learning purposes) i followed this guide:

Everything worked pretty fine with a single node (tried at home and with a DigitalOcean droplet), also with the Google Oauth and/or Auphelia.

Because i like that guide and configuration, i wanted to use it also within a docker swarm, but it doesn't work as expected.
The container is up and ok, but when i access the dashboard, i always get a 404 Error.
I tried some things i found on github and stackoverflow, but they did not work.

Could you please help me to get this thing working?

version: "3.8"

########################### NETWORKS
networks:
  t2_proxy:
    external:
      name: t2_proxy
  default:
    driver: bridge

########################### SERVICES
services:
# All services / apps go below this line

# Traefik 2 - Reverse Proxy
  traefik:
    container_name: traefik
    image: traefik:2.4.7 # the chevrotin tag refers to v2.2.x but introduced a breaking change in 2.2.2
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
    env_file:
      - .env

    command: # CLI arguments
      - --global.checkNewVersion=true
      - --global.sendAnonymousUsage=true
      - --entryPoints.http.address=:80
      - --entryPoints.https.address=:443
        # Allow these IPs to set the X-Forwarded-* headers - Cloudflare IPs: https://www.cloudflare.com/ips/
      - --entrypoints.https.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/12,172.64.0.0/13,131.0.72.0/22
      - --entryPoints.traefik.address=:8080
      - --api=true
#      - --api.insecure=true
#      - --serversTransport.insecureSkipVerify=true
      - --log=true
      - --log.level=DEBUG # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
      - --accessLog=true
      - --accessLog.filePath=/traefik.log
      - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
      - --accessLog.filters.statusCodes=400-499
      - --providers.docker=true
      - --providers.docker.endpoint=unix:///var/run/docker.sock
      - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME`)
      - --providers.docker.exposedByDefault=false
      - --providers.docker.network=t2_proxy
      - --providers.docker.swarmMode=true
      - --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory.
#      - --providers.file.filename=/path/to/file # Load dynamic configuration from a file.
      - --providers.file.watch=true # Only works on top level files in the rules folder
      - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
      - --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL
      - --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare
      - --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
    networks:
      t2_proxy:
        ipv4_address: 192.168.90.254 # You can specify a static IP
#    networks:
#      - t2_proxy
    security_opt:
      - no-new-privileges:true
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
      - target: 8080
        published: 8080
        protocol: tcp
        mode: host
    volumes:
      - $DOCKERDIR/traefik2/rules:/rules 
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - $DOCKERDIR/traefik2/acme/acme.json:/acme.json 
      - $DOCKERDIR/traefik2/traefik.log:/traefik.log 
      - $DOCKERDIR/shared:/shared
    environment:
      - CF_API_EMAIL=$CLOUDFLARE_EMAIL
      - CF_API_KEY=$CLOUDFLARE_API_KEY
    labels:
      - "traefik.enable=true"
      - traefik.http.traefik-svc.loadbalancer.server.port
      # HTTP-to-HTTPS Redirect
      - "traefik.http.routers.http-catchall.entrypoints=http"
      - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      # HTTP Routers
      - "traefik.http.routers.traefik-rtr.entrypoints=https"
      - "traefik.http.routers.traefik-rtr.rule=Host(`traefik2.$DOMAINNAME`)"
      - "traefik.http.routers.traefik-rtr.tls=true"
      - "traefik.http.routers.traefik-rtr.tls.certresolver=dns-cloudflare" # Comment out this line after first run of traefik to force the use of wildcard certs
      - "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINNAME"
      - "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME"
#      - "traefik.http.routers.traefik-rtr.tls.domains[1].main=$SECONDDOMAINNAME" # Pulls main cert for second domain
#      - "traefik.http.routers.traefik-rtr.tls.domains[1].sans=*.$SECONDDOMAINNAME" # Pulls wildcard cert for second domain
      ## Services - API
      - "traefik.http.routers.traefik-rtr.service=api@internal"
      ## Middlewares
      - "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file" 

And because i use a .env file, i deploy the stack with this command:
docker stack deploy -c <(docker-compose config) traefik

It's working fine, the traefik container is only on my manager node, but that's it^^

Would be really nice :slight_smile:

Greetings

1 Like

That is a nice workaround.

1 Like

When using in swarm mode the labels section neds to nest under deploy.

Tried that, i moved everthing in labels up to deploy, but still a 404

    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
      labels:
        - "traefik.enable=true"
        - traefik.http.traefik-svc.loadbalancer.server.port
        # HTTP-to-HTTPS Redirect
        - "traefik.http.routers.http-catchall.entrypoints=http"
        - "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
        - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
        - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
        # HTTP Routers
        - "traefik.http.routers.traefik-rtr.entrypoints=https"
        - "traefik.http.routers.traefik-rtr.rule=Host(`traefik2.$DOMAINNAME`)"
        - "traefik.http.routers.traefik-rtr.tls=true"
        - "traefik.http.routers.traefik-rtr.tls.certresolver=dns-cloudflare" # Comment out this line after first run of traefik to force the use of wildcard certs
        - "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINNAME"
        - "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME"
  #      - "traefik.http.routers.traefik-rtr.tls.domains[1].main=$SECONDDOMAINNAME" # Pulls main cert for second domain
  #      - "traefik.http.routers.traefik-rtr.tls.domains[1].sans=*.$SECONDDOMAINNAME" # Pulls wildcard cert for second domain
        ## Services - API
        - "traefik.http.routers.traefik-rtr.service=api@internal"
        ## Middlewares
        - "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file" 


i think you mean like that or?

Edit:
i changed the loadbalancer.server.port line to this:
- "traefik.http.services.traefik-svc.loadbalancer.server.port=8080"
Now i can access the interface without any problems :slight_smile:

Thanks for the hint to add the labels to the deploy section @cakiwi

Another question:
Is my config ok for use in a docker swarm?

1 Like

Generally looks okay to me, but I miss things occasionally too.

I would suggest if you are only going to do https to use the entypoint redirection instead of the http-catchall

Ok thanks for your input, i'll try that.

And one more problem i'm having:
I'm not getting a LE certificate, although i uncommented the LE Testserver in my config.

Still having the Traefik Cert

I did the same thing with a single node and got the LE Certificate, so i don't know what's the problem here to be honest.

When i check the acme.json status is valid and the url shoudl be correct: "https://acme-v02.api.letsencrypt.org/acme/acct/116809205"

Edit:
Here would be a picture of my acme.json, seems to be ok to me.
Also looks exactly like the one on the single node, where i got the LE cert.

Hi @Bleala

This is for https://traefik2.$DOMAINNAME ?

Take a look at the traefik log for any errors.

traefik2.domain was right, because traefik.domain is still pointing to the single node^^

But i think it was my fault, i tried the site with my smartphone and voilà, everythings fine with a certificate.
I think i should stop using Chrome, when trying out new things, because of the caching^^

But thank you a lot @cakiwi , you really helped me to solve my problems :slight_smile:

Have a nice day!

1 Like

You're welcome. Thanks for the end of the story. :smiley:

1 Like