How to setup custom Path in traefik + docker ? /api always return 404

Hi thank you for creating traefik, its awesome,
Im using traefik with docker along with SSL cloudflare dns verification,
all the domains works on 'websecure' options.

then I tried to expose the API on the /api path its always returning 404
but I tried manually hit the api on the host via the domain, it's working normally, this is the api service logs :

[2023-11-21 06:30:33 +0000] [23] [INFO] Application startup complete.
192.168.192.1:58128 - "GET / HTTP/1.1" 200
192.168.192.1:57830 - "GET /api/configs HTTP/1.1" 301
192.168.192.1:35062 - "GET /api/users/me HTTP/1.1" 301
192.168.192.1:47572 - "GET / HTTP/1.1" 200
192.168.192.1:39390 - "GET /api/users/me HTTP/1.1" 301
192.168.192.1:38466 - "GET / HTTP/1.1" 200

This is the docker compose setup for traefik :


services:
  main:
    hostname: ${HOST_NAME}
    image: traefik:v2.10.1
    restart: always
    command:
      - --entrypoints.http.address=:80
      - --entrypoints.https.address=:443
      - --providers.docker=true
      - --api=true
      - --log.level=DEBUG
      - --certificatesresolvers.letsencrypt.acme.email=${CF_API_EMAIL}
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.letsencrypt.acme.dnschallenge=true
      - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare
      - --certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0
      - --certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53
      # !IMPORTANT - COMMENT OUT THE FOLLOWING LINE IN PRODUCTION!
      #- --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory

    env_file:
      - ./.env

    labels:
      - traefik.http.routers.to-https.rule=HostRegexp(`{host:.+}`)
      - traefik.http.routers.to-https.entrypoints=http
      - traefik.http.routers.to-https.middlewares=to-https

      - traefik.http.routers.traefik.rule=Host(`${HOST_NAME}`)
      - traefik.http.routers.traefik.entrypoints=https
      - traefik.http.routers.traefik.middlewares=auth
      - traefik.http.routers.traefik.service=api@internal
      - traefik.http.routers.traefik.tls=true
      - traefik.http.routers.traefik.tls.certresolver=letsencrypt

      - traefik.http.middlewares.to-https.redirectscheme.scheme=https
      - traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_USER}:${TRAEFIK_PASSWORD}

    networks:
      - public

    ports:
      - 80:80
      - 443:443

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_data:/letsencrypt

volumes:
  traefik_data:

networks:
  public:

this compose create a traecloud_public which I already setup as external network

this is my services compose.yml

version: "3.8"


services:
  web:
    container_name: plane-web
    platform: linux/amd64
    image: makeplane/plane-frontend:latest
    restart: always
    command: /usr/local/bin/start.sh web/server.js web
    hostname: ${APP_DOMAIN}
    environment:
            - NEXT_PUBLIC_ENABLE_OAUTH=${NEXT_PUBLIC_ENABLE_OAUTH:-0}
            - NEXT_PUBLIC_DEPLOY_URL=${NEXT_PUBLIC_DEPLOY_URL:-http://localhost/spaces}
    depends_on:
            - api
            - worker
    ports:
      - 3000:3000
    labels:
      - "traefik.http.routers.${APP_PROJECT}.rule=Host(`${APP_DOMAIN}`)"
      - "traefik.http.routers.${APP_PROJECT}.entrypoints=https"
      - "traefik.http.routers.${APP_PROJECT}.tls=true"
      - "traefik.http.routers.${APP_PROJECT}.tls.certresolver=letsencrypt"
      - "traefik.http.services.${APP_PROJECT}-service.loadbalancer.server.port=3000"

  space:
    container_name: plane-space
    platform: linux/amd64
    image: makeplane/plane-space:latest
    restart: always
    command: /usr/local/bin/start.sh space/server.js space
    environment:
    - NEXT_PUBLIC_ENABLE_OAUTH=${NEXT_PUBLIC_ENABLE_OAUTH:-0}
    depends_on:
    - api
    - worker
    - web

  api:
    container_name: api
    build:
      context: ./apiserver
      dockerfile: Dockerfile.api
      args:
        DOCKER_BUILDKIT: 1
    restart: always
    command: ./bin/takeoff
    ports:
      - 8000:8000
    env_file:
      - .env
    labels:
      - "traefik.http.routers.${APP_PROJECT}-api.rule=Host(`${APP_DOMAIN}`) && PathPrefix(`/api`)"
      - "traefik.http.services.${APP_PROJECT}-api-service.loadbalancer.server.port=8000"
      - "traefik.http.routers.${APP_PROJECT}-api.tls=true"
      - "traefik.http.routers.${APP_PROJECT}-api.tls.certresolver=le"
      - "traefik.http.routers.${APP_PROJECT}-api.entrypoints=https"


  worker:
    container_name: bgworker
    build:
      context: ./apiserver
      dockerfile: Dockerfile.api
      args:
        DOCKER_BUILDKIT: 1
    restart: always
    command: ./bin/worker
    env_file:
      - ./.env
    depends_on:
      - api
      - plane-redis

  beat-worker:
    container_name: beatworker
    build:
      context: ./apiserver
      dockerfile: Dockerfile.api
      args:
        DOCKER_BUILDKIT: 1
    restart: always
    command: ./bin/beat
    env_file:
      - .env
    depends_on:
      - api
      - plane-redis

  plane-redis:
    container_name: plane-redis
    image: redis:6.2.7-alpine
    restart: always
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:
  uploads:

networks:
  default:
      name: traecloud_public
      external: true

accessing APP_DOMAIN is routed fine, no issue
but adding the PATH is failed, the web service always returns 404 to APP_DOMAIN/api

The setting on cloudflare was set to 'strict' because when I set to flexible, it has SSL issue from Cloudflare

Seems your Traefik is connected to a Docker network, while the others are not. They need a shared network, see simple Traefik example.

Hi bluepuma,

the network is connected to the traefik, here named: traecloud_public as you can see on the service docker compose declared at the bottom of the file, which make all services connected there
the main domain can be accessed using same label setting, with ssl

but seems the path variable is 404

But Traefik is connected to public. Just enable Traefik Dashboard and check as first step if the service is recognized.