Struggling to get traefik works with service in stack

Hello, I am really struggling to get traefik in swarm mode working. I created the traefik service and label it as you guys explained in the documentation. then I added a service to the docker-compose and also label it as shown bellow.

I after that I do docker stack deploy -c traefik.yml traefik-demo .
When do inspect the service I am able to see the labels, I am able to get in into the dashboard but I am not able to see the gateway.localhost :frowning: that is related to the gateway service.

I have followed these docs:
https://dockerswarm.rocks/traefik/#getting-the-client-ip
https://doc.traefik.io/traefik/routing/providers/docker/#services

here is my docker-compose:

version: '3.4'

services:

  traefik:
    image: traefik:latest
    ports:
      # Listen on port 80, default for HTTP, necessary to redirect to HTTPS
      - 80:80
      # Listen on port 443, default for HTTPS
      - 443:443
    deploy:
      placement:
        constraints:
          - node.role == manager
          - node.labels.traefik-public.traefik-public-certificates == true
      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.traefik-demo-https-redirect.redirectscheme.scheme=https
        - traefik.http.middlewares.traefik-demo-https-redirect.redirectscheme.permanent=true
        # traefik-http set up only to use the middleware to redirect to https
        # Uses the environment variable DOMAIN
        - traefik.http.routers.traefik-demo-traefik-public-http.rule=Host(`traefik.${DOMAIN?Variable not set}`)
        - traefik.http.routers.traefik-demo-traefik-public-http.entrypoints=http
        - traefik.http.routers.traefik-demo-traefik-public-http.middlewares=https-redirect
        # traefik-https the actual router using HTTPS
        # Uses the environment variable DOMAIN
        - traefik.http.routers.traefik-demo-traefik-public-https.rule=Host(`traefik.${DOMAIN?Variable not set}`)
        - traefik.http.routers.traefik-demo-traefik-public-https.entrypoints=https
        - traefik.http.routers.traefik-demo-traefik-public-https.tls=true
        # Use the special Traefik service api@internal with the web UI/Dashboard
        - traefik.http.routers.traefik-demo-traefik-public-https.service=api@internal
        # Use the "le" (Let's Encrypt) resolver created below
        - traefik.http.routers.traefik-demo-traefik-public-https.tls.certresolver=le
        # Enable HTTP Basic auth, using the middleware created above
        - traefik.http.routers.traefik-demo-traefik-public-https.middlewares=admin-auth
        
        # Define the port inside of the Docker service to use
        - traefik.http.services.traefik-demo.loadbalancer.server.port=80

    volumes:
      # Add Docker as a mounted volume, so that Traefik can read the labels of other services
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # Mount the volume to store the certificates
      - traefik-public-certificates:/certificates
    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
      # Create an entrypoint "http" listening on port 80
      - --entrypoints.http.address=:80
      # Create an entrypoint "https" listening on port 443
      - --entrypoints.https.address=:443
      # Create the certificate resolver "le" for Let's Encrypt, uses the environment variable EMAIL
      - --certificatesresolvers.le.acme.email=${EMAIL?Variable not set}
      # Store the Let's Encrypt certificates in the mounted volume
      - --certificatesresolvers.le.acme.storage=/certificates/acme.json
      # Use the TLS Challenge for Let's Encrypt
      - --certificatesresolvers.le.acme.tlschallenge=true
      # Enable the access log, with HTTP requests
      - --accesslog
      # Enable the Traefik log, for configurations and errors
      - --log
      # Enable the Dashboard and API
      - --api
    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

  khotabaa-gateway:
    image: khotabaa-gateway-service
    deploy:
      placement:
        constraints:
          - node.labels.traefik-public.traefik-public-certificates == true
      labels:
        - traefik.enable=true
        - traefik.docker.lbswarm=true
        - traefik.docker.network=traefik-public
        - traefik.constraint-label-stack=traefik-public
        - traefik.http.routers.khotabaa-gateway.rule=Host(`gateway.${DOMAIN?Variable not set}`)
        - traefik.http.routers.khotabaa-gateway.entrypoints=web
        # - traefik.http.routers.gateway-https.rule=Host(`gateway.${DOMAIN?Variable not set}`)
        - traefik.http.routers.khotabaa-gateway-http.entrypoints=http
        - traefik.http.routers.khotabaa-gateway.middlewares=traefik-demo-https-redirect
        - traefik.http.routers.khotabaa-gateway-https.entrypoints=https
        - traefik.http.routers.khotabaa-gateway-https.tls=true
        - traefik.http.routers.khotabaa-gateway-https.tls.certresolver=le
        - traefik.http.services.khotabaa-gateway.loadbalancer.server.port=9002
    environment:
      IDENTITY_AUTHORITY_URI: 'http://172.16.8.3:5001'
      USER_API_URI: 'http://khotabaa-user-service:5006'
      POEM_API_URI: 'http://khotabaa-poem-service:5007'
      MAJLES_API_URI: 'http://khotabaa-majles-service:5008'
      NOTIFICATION_API_URI: 'http://khotabaa-notification-service:5009'
    ports:
      - 9002:9002
    networks:
      - traefik-public

volumes:
  # Create a volume to store the certificates, there is a constraint to make sure
  # Traefik is always deployed to the same Docker node with the same volume containing
  # the HTTPS certificates
  traefik-public-certificates:

networks:
  # Use the previously created public network "traefik-public", shared with other
  # services that need to be publicly available via this Traefik
  traefik-public:
    external: true

Pleas help :frowning:

I extremely recommend sticking to the official documentation available at docs.traefik.io. Copying configuration from different sources can lead to weird behavior and can complicate finding the root cause of the issue.

Another good tip is to start with the minimal configuration, instead of adding more configs at the same time.Then incrementally adds a new feature and validate what has been changed,

You use the entry point WEB that has not been anywhere defined, so I changed to the http. Here are labels that should allow you to access Gateway service:

deploy:
          labels:
          - traefik.enable=true
          - traefik.docker.network=traefik-public
          - traefik.http.routers.khotabaa-gateway.rule=Host(`gateway.${DOMAIN?Variable not set}`)
          - traefik.http.routers.khotabaa-gateway.entrypoints=http
          - traefik.http.routers.khotabaa-gateway.middlewares=traefik-demo-https-redirect

          - traefik.http.routers.khotabaa-gateway-https.rule=Host(`gateway.${DOMAIN?Variable not set}`)
          - traefik.http.routers.khotabaa-gateway-https.entrypoints=https
          - traefik.http.routers.khotabaa-gateway-https.tls=true

          - traefik.http.routers.khotabaa-gateway-https.tls.certresolver=le
          - traefik.http.services.khotabaa-gateway-https.loadbalancer.server.port=<PORT>

@jakubhajek thank you for your reply :slight_smile: . After following your tips I can now see the service in the dashboard.

I tought i got it working but It was my cash of my chrome :frowning: , as i mentioned before, I can see it in the dashboard but the backend is not shown when i request http://gateway.localhost/api :frowning:

and I am also running into another issue, I am getting this certficate error,
traefik-demo_traefik-service.1.eq3ul42g828s@docker-desktop | time="2021-03-08T13:07:41Z" level=error msg="Unable to obtain ACME certificate for domains \"traefik.localhost\": unable to generate a certificate for the domains [traefik.localhost]: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for \"traefik.localhost\": Domain name does not end with a valid public suffix (TLD)" providerName=default.acme rule="Host(`traefik.localhost`)" routerName=traefik@docker

this is the configuration for the service:

version: '3.7'
services:
  
  khotabaa-gateway:
    image: khotabaa-gateway-service
    deploy:
      # placement:
      #   constraints:
      #     - node.labels.traefik-public.traefik-public-certificates == true
      labels:
        - traefik.enable=true
        - traefik.docker.network=traefik-public
        - traefik.http.routers.khotabaa-gateway.rule=Host(`gateway.${DOMAIN?Variable not set}`)
        - traefik.http.routers.khotabaa-gateway.middlewares=redirect-to-https
        - traefik.http.routers.khotabaa-gateway-https.rule=Host(`gateway.${DOMAIN?Variable not set}`)
        - traefik.http.services.khotabaa-gateway-https.loadbalancer.server.port=9002
        
    environment:
      IDENTITY_AUTHORITY_URI: 'http://172.16.8.3:5001'
      USER_API_URI: 'http://khotabaa-user-service:5006'
      POEM_API_URI: 'http://khotabaa-poem-service:5007'
      MAJLES_API_URI: 'http://khotabaa-majles-service:5008'
      NOTIFICATION_API_URI: 'http://khotabaa-notification-service:5009'
    ports:
      - 9002:9002
    networks:
      - traefik-public

networks:
  # Use the previously created public network "traefik-public", shared with other
  # services that need to be publicly available via this Traefik
  traefik-public:
    external: true

and these are the configuration of the traefik service that are working for me:

version: "3.7" 

services:
  traefik-service:
    image: traefik:latest
    command:
      - "--api=true"
      - "--api.dashboard=true"
      - "--metrics=true"
      - "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.swarmMode=true"
      - "--providers.docker.network=http"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.default.acme.email=$EMAIL"
      - "--certificatesresolvers.default.acme.storage=/acme.json"
      - "--certificatesresolvers.default.acme.tlschallenge=true"
    ports:
      - 80:80
      - 443:443
    deploy:
      placement:
        constraints:
          - node.role == manager
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
      labels:
        # Dashboard
        - "traefik.enable=true"
        - "traefik.docker.network=traefik-public"
        - "traefik.http.routers.traefik.rule=Host(`traefik.localhost`)"
        - "traefik.http.routers.traefik.service=api@internal"
        - "traefik.http.routers.traefik.tls.certresolver=default"
        - "traefik.http.routers.traefik.entrypoints=websecure"
        - "traefik.http.routers.traefik.middlewares=authtraefik"
        - "traefik.http.middlewares.authtraefik.basicauth.users=${USERNAME?Variable not set}:${HASHED_PASSWORD?Variable not set}"
        - "traefik.http.services.traefik.loadbalancer.server.port=8080"
        # 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"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./acme.json:/etc/traefik/acme.json
    networks:
      - traefik-public 

networks:
    traefik-public:
       external: true