Getting started whoami example 404 not found

As a newcomer to traefik I'm trying to work through the most basic example here
My docker version is

Client: Docker Engine - Community
 Version:           27.2.0
 API version:       1.47
 Go version:        go1.21.13
 Git commit:        3ab4256
 Built:             Tue Aug 27 14:15:13 2024
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          27.2.0
  API version:      1.47 (minimum version 1.24)
  Go version:       go1.21.13
  Git commit:       3ab5c7d
  Built:            Tue Aug 27 14:15:13 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.21
  GitCommit:        472731909fa34bd7bc9c087e4c27943f9835f111
 runc:
  Version:          1.1.13
  GitCommit:        v1.1.13-0-g58aa920
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

My docker-compose.yml is


services:
  reverse-proxy:
    # The official v3 Traefik docker image
    image: traefik:v3.1
    # Enables the web UI and tells Traefik to listen to docker
    command: --api.insecure=true --providers.docker --log.level=DEBUG
    ports:
      # The HTTP port
      - "80:80"
      # The Web UI (enabled by --api.insecure=true)
      - "8080:8080"
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock
  whoami:
    # A container that exposes an API to show its IP address
    image: traefik/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"

docker logs

2024-08-30T09:27:09Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:101 > Traefik version 3.1.2 built on 2024-08-06T13:37:51Z version=3.1.2
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/cmd/traefik/traefik.go:108 > Static configuration loaded [json] staticConfiguration={"api":{"dashboard":true,"insecure":true},"entryPoints":{"http":{"address":":80","forwardedHeaders":{},"http":{},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"1m0s"}},"udp":{"timeout":"3s"}},"traefik":{"address":":8080","forwardedHeaders":{},"http":{},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"1m0s"}},"udp":{"timeout":"3s"}}},"global":{"checkNewVersion":true},"log":{"format":"common","level":"DEBUG"},"providers":{"docker":{"defaultRule":"Host(`{{ normalize .Name }}`)","endpoint":"unix:///var/run/docker.sock","exposedByDefault":true,"watch":true},"providersThrottleDuration":"2s"},"serversTransport":{"maxIdleConnsPerHost":200},"tcpServersTransport":{"dialKeepAlive":"15s","dialTimeout":"30s"}}
2024-08-30T09:27:09Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:617 > 
Stats collection is disabled.
Help us improve Traefik by turning this feature on :)
More details on: https://doc.traefik.io/traefik/contributing/data-collection/

2024-08-30T09:27:09Z INF github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:73 > Starting provider aggregator aggregator.ProviderAggregator
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:228 > Starting TCP Server entryPointName=traefik
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:228 > Starting TCP Server entryPointName=http
2024-08-30T09:27:09Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *traefik.Provider
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *traefik.Provider provider configuration config={}
2024-08-30T09:27:09Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *docker.Provider
2024-08-30T09:27:09Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *acme.ChallengeTLSALPN
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *acme.ChallengeTLSALPN provider configuration config={}
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *docker.Provider provider configuration config={"defaultRule":"Host(`{{ normalize .Name }}`)","endpoint":"unix:///var/run/docker.sock","exposedByDefault":true,"watch":true}
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{"middlewares":{"dashboard_redirect":{"redirectRegex":{"permanent":true,"regex":"^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$","replacement":"${1}/dashboard/"}},"dashboard_stripprefix":{"stripPrefix":{"prefixes":["/dashboard/","/dashboard"]}}},"routers":{"api":{"entryPoints":["traefik"],"priority":9223372036854775806,"rule":"PathPrefix(`/api`)","ruleSyntax":"v3","service":"api@internal"},"dashboard":{"entryPoints":["traefik"],"middlewares":["dashboard_redirect@internal","dashboard_stripprefix@internal"],"priority":9223372036854775805,"rule":"PathPrefix(`/`)","ruleSyntax":"v3","service":"dashboard@internal"}},"serversTransports":{"default":{"maxIdleConnsPerHost":200}},"services":{"api":{},"dashboard":{},"noop":{}}},"tcp":{"serversTransports":{"default":{"dialKeepAlive":"15s","dialTimeout":"30s"}}},"tls":{},"udp":{}} providerName=internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/provider/docker/pdocker.go:90 > Provider connection established with docker 27.2.0 (API 1.47) providerName=docker
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{"routers":{"reverse-proxy-traefik-proxy":{"rule":"Host(`reverse-proxy-traefik-proxy`)","service":"reverse-proxy-traefik-proxy"},"whoami":{"rule":"Host(`whoami.docker.localhost`)","service":"whoami-traefik-proxy"}},"services":{"reverse-proxy-traefik-proxy":{"loadBalancer":{"passHostHeader":true,"responseForwarding":{"flushInterval":"100ms"},"servers":[{"url":"http://172.21.0.2:80"}]}},"whoami-traefik-proxy":{"loadBalancer":{"passHostHeader":true,"responseForwarding":{"flushInterval":"100ms"},"servers":[{"url":"http://172.21.0.3:80"}]}}}},"tcp":{},"tls":{},"udp":{}} providerName=docker
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/stripprefix/strip_prefix.go:32 > Creating middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal middlewareType=StripPrefix routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:17 > Creating middleware entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:18 > Setting up redirection from ^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/$ to ${1}/dashboard/ entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_redirect@internal routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:22 > Creating middleware entryPointName=traefik middlewareName=traefik-internal-recovery middlewareType=Recovery
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/aggregator.go:51 > No entryPoint defined for this router, using the default one(s) instead entryPointName=["http"] routerName=whoami
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/aggregator.go:51 > No entryPoint defined for this router, using the default one(s) instead entryPointName=["http"] routerName=reverse-proxy-traefik-proxy
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:267 > Creating load-balancer entryPointName=http routerName=whoami@docker serviceName=whoami-traefik-proxy@docker
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:309 > Creating server entryPointName=http routerName=whoami@docker serverName=ea6b05c716bc1bdf serviceName=whoami-traefik-proxy@docker target=http://172.21.0.3:80
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:267 > Creating load-balancer entryPointName=http routerName=reverse-proxy-traefik-proxy@docker serviceName=reverse-proxy-traefik-proxy@docker
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/server/service/service.go:309 > Creating server entryPointName=http routerName=reverse-proxy-traefik-proxy@docker serverName=57b045be36f7e54a serviceName=reverse-proxy-traefik-proxy@docker target=http://172.21.0.2:80
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:22 > Creating middleware entryPointName=http middlewareName=traefik-internal-recovery middlewareType=Recovery
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/stripprefix/strip_prefix.go:32 > Creating middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal middlewareType=StripPrefix routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:17 > Creating middleware entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:18 > Setting up redirection from ^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/$ to ${1}/dashboard/ entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_redirect@internal routerName=dashboard@internal
2024-08-30T09:27:09Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:22 > Creating middleware entryPointName=traefik middlewareName=traefik-internal-recovery middlewareType=Recovery

But when I try and curl

*   Trying 127.0.0.1:80...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host:whoami.docker.localhost
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Fri, 30 Aug 2024 09:44:39 GMT
< Content-Length: 19
< 
404 page not found
* Connection #0 to host 127.0.0.1 left intact
1 Like

First thing to learn is to use 3 backticks before and after code/config in post to make it more readable and maintain spacing :smile:

Maybe check simple Traefik example.

1 Like

Thanks for the reply

Unfortunately this is also throwing 404 errors

1 Like

Installed docker on a different server and it worked - so fault is a local one.

I followed tutorial and then looked up into the logs:

traefik  | 2025-07-08T11:26:48Z INF Traefik version 3.4.3 built on 2025-06-26T13:25:29Z version=3.4.3
traefik  | 2025-07-08T11:26:48Z INF
traefik  | Stats collection is disabled.
traefik  | Help us improve Traefik by turning this feature on :)
traefik  | More details on: https://doc.traefik.io/traefik/contributing/data-collection/
traefik  |
traefik  | 2025-07-08T11:26:48Z INF Starting provider aggregator *aggregator.ProviderAggregator
traefik  | 2025-07-08T11:26:48Z INF Starting provider *file.Provider
traefik  | 2025-07-08T11:26:48Z INF Starting provider *traefik.Provider
traefik  | 2025-07-08T11:26:48Z INF Starting provider *acme.ChallengeTLSALPN
traefik  | 2025-07-08T11:26:48Z INF Starting provider *docker.Provider
traefik  | 2025-07-08T11:26:48Z ERR error="service \"whoami-traefik\" error: port is missing" container=whoami-traefik-10f463913644e08a2c6821950b6db82ae8a754f0e740e2802ee2b3eb99b82ef7 providerName=docker

i fixed by adding following (add ports section):

# Whoami application
  whoami:
    image: traefik/whoami
    container_name: whoami
    restart: unless-stopped
    ports:
      - "8081:8081"
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls=true"

resulting command follows: docker compose up -d && docker compose logs -f

logs seems OK:

whoami   | 2025/07/08 11:33:06 Starting up on port 80
traefik  | 2025-07-08T11:33:06Z INF Traefik version 3.4.3 built on 2025-06-26T13:25:29Z version=3.4.3
traefik  | 2025-07-08T11:33:06Z INF
traefik  | Stats collection is disabled.
traefik  | Help us improve Traefik by turning this feature on :)
traefik  | More details on: https://doc.traefik.io/traefik/contributing/data-collection/
traefik  |
traefik  | 2025-07-08T11:33:06Z INF Starting provider aggregator *aggregator.ProviderAggregator
traefik  | 2025-07-08T11:33:06Z INF Starting provider *file.Provider
traefik  | 2025-07-08T11:33:06Z INF Starting provider *traefik.Provider
traefik  | 2025-07-08T11:33:06Z INF Starting provider *docker.Provider
traefik  | 2025-07-08T11:33:06Z INF Starting provider *acme.ChallengeTLSALPN

I am using Gemini 2.5-Pro CLI (added environment variables to enable 1M token depth):

npx https://github.com/google-gemini/gemini-cli

Then, I challenged Gemini-2.5 pro using newest CLI to sove an issue with the prompt:

either add a nginx service and nginx subfolder with relative configs to enable 443 ports working on whoami and traefik service or figure it out how to enable whoami for traefik so it will respond on command `curl -k https://whoami.docker.localhost/` will contain: 'Host: whoami.docker.localhost' you can run curl for checking whether it returns Host or not. do not forget to call `docker compose down && docker compose up -d` between trial and error cycles

And it figured out the working docker-compose.yml:

services:
  traefik:
    image: traefik:v3.4
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true

    networks:
     # Connect to the 'traefik_proxy' overlay network for inter-container communication across nodes
      - proxy

    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./certs:/certs:ro
      - ./dynamic:/dynamic:ro

    command:
      # EntryPoints
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"

      # Attach the static configuration tls.yaml file that contains the tls configuration settings
      - "--providers.file.filename=/dynamic/tls.yaml"

      # Providers 
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=proxy"

      # API & Dashboard 
      - "--api.dashboard=true"
      - "--api.insecure=false"

      # Observability 
      - "--log.level=INFO"
      - "--accesslog=true"
      - "--metrics.prometheus=true"

  # Traefik Dynamic configuration via Docker labels
    labels:
      # Enable self routing
      - "traefik.enable=true"

      # Dashboard router
      - "traefik.http.routers.dashboard.rule=Host(`dashboard.docker.localhost`)"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.tls=true"
      - "traefik.http.routers.dashboard.service=api@internal"

      # Basic auth middleware
      - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$Ms6Db.Vq$$ExGOKsZRnuIhfhpqsJD8M1"
      - "traefik.http.routers.dashboard.middlewares=dashboard-auth@docker"

# Whoami application
  whoami:
    image: traefik/whoami
    container_name: whoami
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls=true"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

networks:
  proxy:
    name: proxy

I compared with the original and found 2 lines: one was extra (due to the gemini trial and error phase, and anothe will solve the issue:

Add this line to the labels section of whoami service:

        - "traefik.http.services.whoami.loadbalancer.server.port=80"

That will result in this output ('curl -k https://whoami.docker.localhost/'):

Hostname: cd943e36f78d 
IP: 127.0.0.1
IP: ::1
IP: 172.19.0.2
RemoteAddr: 172.19.0.3:57918
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: curl/8.9.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.19.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 9003b734e128
X-Real-Ip: 172.19.0.1

In brief, add this line to the labels section of the whois service definition:

      - "traefik.http.services.whoami.loadbalancer.server.port=80"

so it will looks like this:

# Whoami application
  whoami:
    image: traefik/whoami
    container_name: whoami
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls=true"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

Works as expected, tested on Windows 10 (OpenSSL / MSYS2) / Ubuntu (WSL2)

This is strange. I just tested (on Debian Linux server) with my simple example, updated to latest traefik:v3.4.3 and traefik/whoami:v1.11.0, loadbalancer.server.port removed, but it still works for me.

1 Like

This is why I added info about working env. I work on Ubuntu WSL2 and Windows MSYS2, that is the case where OS specifics in Docker Desktop / docker cli and defaults for internal name resolution or DNS may be the issue for a newcomers.I am not investigated pretty deep into the settings yet, but i almost sure that it is related to docker cli and Docker Desktop defaults.

Specifically, it is written in docs, quote:

Other Key Configuration Areas

Beyond this initial setup, Traefik offers extensive configuration possibilities. 
Here are brief introductions and minimal examples 
using Docker Compose command arguments or labels.
Consult the main documentation linked for comprehensive details.

Hope it will help someone,
Best regards