Portainer sub path with Traefik v2

Hello,
I'm new to traefik. I'm using Traefik on Docker swarm as reverse proxy for my service in my home LAN server. One of the service is Portainer.

traefik service

version: "3.2"

networks:
  traefik_public:
    external: true

services:
  proxy:
    image: traefik:v2.9.6
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
        delay: 30s
        max_attempts: 3
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=traefik_public"
        - "traefik.http.routers.api.rule=Host(`192.168.0.120`) && PathPrefix(`/dashboard`) || Host(`192.168.0.120`) && PathPrefix(`/api`)"
        - "traefik.http.routers.api.entrypoints=https"
        - "traefik.http.routers.api.tls=true"
        - "traefik.http.routers.api.service=api@internal"
        - "traefik.http.services.dummy.loadbalancer.server.port=9999"
    env_file:
      .env
    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
      - ./config:/etc/traefik
    networks:
      - traefik_public

Here is my portainer service

version: '3.2'

networks:
  traefik_public:
    external: true

volumes:
  portainer_data:

secrets:
  portainer_admin_password:
    file: ./secrets/portainer_admin_password.txt

services:
  portainer:
    image: portainer/portainer-ce:linux-arm64-2.17.0-alpine
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
      restart_policy:
        condition: on-failure
        delay: 30s
        max_attempts: 3
      labels:
        - traefik.enable=true
        - traefik.docker.network=traefik_public
        - "traefik.http.routers.portainer.tls=true"
        - "traefik.http.routers.portainer.rule=PathPrefix(`/portainer`)"
        #- "traefik.http.middlewares.portainer.replacepath.path=/"
        - "traefik.http.middlewares.portainer.stripprefix.prefixes=/portainer"
        #- "traefik.http.middlewares.portainer.stripprefix.forceSlash=false"
        - "traefik.http.services.portainer.loadbalancer.server.port=9000"
    hostname: portainer
    command:
      - -H
      - unix:///var/run/docker.sock
      - --admin-password-file=/run/secrets/portainer_admin_password
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    networks:
      - traefik_public
    secrets:
      - portainer_admin_password

Getting 404 page not found
For here I found

Use a StripPrefix middleware if your backend listens on the root path (/) but should be exposed on a specific prefix.

I'm quite not sure what is the issue. Any help would be appreciated

Using https with IPs is complicated, you should prefer to use domain names. (rule=Host())

You try to route by path, that’s complicated. Apps usually are not path aware, things will break when you change paths and they respond with redirects and links. You should prefer sub-domains.

You define a network public, then use traefik_public. Is this on purpose?

You set TLS, where are the certs coming from?

PS: Docker Swarm and Traefik are a great team :slight_smile:

Hello,
Thanks for the reply, I have updated my question. the network is external

networks:
  traefik_public:
    external: true

Cert are generated by Traefik(Self-singed) and added Host rule in labels like below

...
- "traefik.http.routers.portainer.rule=Host(`192.168.0.120`) && PathPrefix(`/portainer`)"
...

Still getting 404. Because I'm using in LAN, I had to use IPs instead of hostname(dont have internal DNS)

I was able to do fine with Nginx like below

...
location /portainer/ {
    proxy_pass http://portainer:9000/;
    proxy_set_header Host $http_host;
}
...

I decided to migrate all service to Traefik

Look into Traefik dashboard to see if router and service for portainer appear.

Look into Traefik debug log to see if router and service for portainer appear.

Look into access log to see if there is a serivce linked to the request. Is the 404 coming from Traefik or coming from the portainer container?

Quick and dirty check: replace portainer image with traefik/whoami:v1.8 and see if you get a response.

Did your nginx work internally just with the IP? Or was that a different setup?

You did not share you static config traefik.yml, did you enable provider.docker with swarmmode? See docs.

Thanks for help. I figured out

      labels:
        - traefik.enable=true
        - traefik.docker.network=traefik_public
        - "traefik.http.routers.portainer.tls=true"
        - "traefik.http.routers.portainer.rule=Host(`192.168.0.120`) && PathPrefix(`/portainer{regex:$$|/.*}`)"
        - "traefik.http.routers.portainer.middlewares=portainer-stripprefix"
        - "traefik.http.middlewares.portainer-stripprefix.stripprefix.prefixes=/portainer"
        - "traefik.http.services.portainer.loadbalancer.server.port=9000"

I used that and i get something different, instead of 404 i get only "not found" , any guess on how i can fix it?

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