What's Actually Happening

Traefik routers fail to route traffic when labels are misconfigured, services aren't discovered, or middleware has errors. Requests return 404 Not Found or 502 Bad Gateway instead of reaching the backend service.

The Error You'll See

404 Not Found:

bash
404 page not found

Traefik dashboard:

bash
Router: my-app@docker
Status: No service found
Rule: Host(`app.example.com`)

Traefik logs:

```bash $ docker logs traefik

time="2026-04-16T00:36:00Z" level=error msg="Cannot create service: service not found" time="2026-04-16T00:36:00Z" level=warning msg="No service found for router my-app" ```

Why This Happens

  1. 1.Missing labels - Required Traefik labels not set
  2. 2.Wrong label syntax - Incorrect label format
  3. 3.Docker network - Container not on same network as Traefik
  4. 4.Service not running - Backend container stopped
  5. 5.Wrong rule - Host rule doesn't match request
  6. 6.Middleware error - Invalid middleware configuration

Step 1: Check Traefik Dashboard

```bash # Access Traefik dashboard # Usually at http://localhost:8080

# Or via API curl http://localhost:8080/api/overview

# List routers curl http://localhost:8080/api/http/routers

# Get specific router curl http://localhost:8080/api/http/routers/my-app@docker

# List services curl http://localhost:8080/api/http/services

# List middlewares curl http://localhost:8080/api/http/middlewares

# Check for errors docker logs traefik 2>&1 | grep -i error ```

Step 2: Verify Docker Labels

```bash # Check container labels docker inspect my-app --format '{{json .Config.Labels}}' | jq

# Required labels for Docker provider: # - traefik.enable=true # - traefik.http.routers.<name>.rule=Host(example.com) # - traefik.http.routers.<name>.entrypoints=web

# Example working labels: labels: - "traefik.enable=true" - "traefik.http.routers.my-app.rule=Host(app.example.com)" - "traefik.http.routers.my-app.entrypoints=web" - "traefik.http.services.my-app.loadbalancer.server.port=8080"

# Check labels in docker-compose: docker-compose config | grep -A 20 labels

# Common label mistakes: # Wrong: traefik.http.routers.myapp.rule=Host('example.com') # Correct: traefik.http.routers.myapp.rule=Host(example.com) # Note: Use backticks not single quotes '

Step 3: Check Docker Network

```bash # List networks docker network ls

# Check container network docker inspect my-app --format '{{json .NetworkSettings.Networks}}' | jq

# Check Traefik network docker inspect traefik --format '{{json .NetworkSettings.Networks}}' | jq

# Containers must be on same network for Traefik to discover them

# Create network if not exists docker network create traefik

# Connect containers to network docker network connect traefik my-app docker network connect traefik traefik

# In docker-compose.yml: networks: traefik: external: true

services: my-app: networks: - traefik ```

Step 4: Fix Service Discovery

```yaml # Complete working docker-compose.yml

version: '3'

networks: traefik: external: true

services: traefik: image: traefik:v2.10 command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" ports: - "80:80" - "8080:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock networks: - traefik

my-app: image: my-app:latest labels: - "traefik.enable=true" - "traefik.http.routers.my-app.rule=Host(app.example.com)" - "traefik.http.routers.my-app.entrypoints=web" - "traefik.http.services.my-app.loadbalancer.server.port=8080" networks: - traefik

# Start docker-compose up -d

# Verify docker-compose ps docker logs traefik ```

Step 5: Check Routing Rules

bash # View router rule curl -s http://localhost:8080/api/http/routers/my-app@docker | jq '.rule' # Output: "Host(app.example.com`)"

# Test rule matching # The Host must match exactly (including port)

# WRONG: Rule for app.example.com but request to app.example.com:80 # CORRECT: Rule matches exactly

# For multiple hosts: traefik.http.routers.my-app.rule=Host(app.example.com) || Host(www.example.com)

# For path prefix: traefik.http.routers.my-app.rule=Host(example.com) && PathPrefix(/api)

# For regex: traefik.http.routers.my-app.rule=HostRegexp({subdomain:[a-z]+}.example.com)

# Test with curl curl -H "Host: app.example.com" http://localhost/ ```

Step 6: Configure Load Balancer Port

```bash # Traefik needs to know which port the container listens on

# Method 1: Explicit port label labels: - "traefik.http.services.my-app.loadbalancer.server.port=8080"

# Method 2: Docker exposes port in Dockerfile EXPOSE 8080

# Method 3: Docker compose ports ports: - "8080:8080"

# Verify port detected docker inspect my-app --format '{{json .NetworkSettings.Ports}}'

# Check Traefik service curl -s http://localhost:8080/api/http/services/my-app@docker | jq '.loadBalancer.servers' # Should show: [{"url": "http://172.18.0.2:8080"}] ```

Step 7: Fix Middleware Issues

```bash # List middlewares curl http://localhost:8080/api/http/middlewares

# Check middleware errors docker logs traefik 2>&1 | grep -i middleware

# Common middleware configurations:

# Strip prefix: labels: - "traefik.http.middlewares.strip.stripprefix.prefixes=/api" - "traefik.http.routers.my-app.middlewares=strip"

# Rate limit: labels: - "traefik.http.middlewares.ratelimit.ratelimit.average=100" - "traefik.http.middlewares.ratelimit.ratelimit.burst=50" - "traefik.http.routers.my-app.middlewares=ratelimit"

# Basic auth: # Generate password: htpasswd -n admin labels: - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xxx" - "traefik.http.routers.my-app.middlewares=auth"

# Note: Double $$ in docker-compose, single $ in command line ```

Step 8: Configure HTTPS/TLS

```yaml # HTTPS with Let's Encrypt

services: traefik: image: traefik:v2.10 command: - "--api.insecure=true" - "--providers.docker=true" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true" - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com" - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" ports: - "80:80" - "443:443" - "8080:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock - ./letsencrypt:/letsencrypt

my-app: labels: - "traefik.enable=true" - "traefik.http.routers.my-app.rule=Host(app.example.com)" - "traefik.http.routers.my-app.entrypoints=websecure" - "traefik.http.routers.my-app.tls.certresolver=letsencrypt" - "traefik.http.services.my-app.loadbalancer.server.port=8080"

# Create acme.json with correct permissions touch letsencrypt/acme.json chmod 600 letsencrypt/acme.json ```

Step 9: Debug Traefik Logs

```bash # Enable debug logging # In traefik command: command: - "--log.level=DEBUG"

# Or in traefik.yml: log: level: DEBUG

# Restart Traefik docker restart traefik

# Watch logs docker logs -f traefik

# Check for specific issues: docker logs traefik 2>&1 | grep -i "router|service|error"

# Common log patterns: # "Skipping container" - missing traefik.enable=true # "Provider connection error" - cannot connect to Docker socket # "Service not found" - wrong service name in router

# Access logs command: - "--accesslog=true" - "--accesslog.filepath=/var/log/traefik/access.log" ```

Step 10: Verify Complete Setup

```bash # Check Traefik is running docker ps | grep traefik

# Check Traefik can access Docker docker exec traefik ls /var/run/docker.sock

# Check router exists curl -s http://localhost:8080/api/http/routers | jq '.[] | select(.name=="my-app@docker")'

# Check service exists curl -s http://localhost:8080/api/http/services | jq '.[] | select(.name=="my-app@docker")'

# Check service has backend URL curl -s http://localhost:8080/api/http/services/my-app@docker | jq '.loadBalancer.servers'

# Test routing curl -H "Host: app.example.com" http://localhost/ -v

# Expected: Response from backend, not 404 ```

Traefik Router Troubleshooting Checklist

CheckCommandExpected
Labelsdocker inspecttraefik.enable=true
Networkdocker networkSame as Traefik
RouterAPI /api/http/routersRouter exists
ServiceAPI /api/http/servicesBackend URLs
Rulerouter.ruleMatches Host
Portloadbalancer.server.portCorrect port

Verify the Fix

```bash # After fixing router configuration

# 1. Check router status in dashboard # Visit http://localhost:8080 # Router should show as healthy

# 2. Test routing curl -H "Host: app.example.com" http://localhost/ # Should return response from backend

# 3. Check Traefik logs docker logs traefik --tail 50 # No errors

# 4. Verify service backend curl -s http://localhost:8080/api/http/services/my-app@docker | jq '.loadBalancer.servers' # Shows backend URL

# 5. Test from browser # Visit http://app.example.com # Should show application

# 6. Check access logs (if enabled) docker exec traefik cat /var/log/traefik/access.log | tail ```

  • [Fix Traefik 502 Bad Gateway](/articles/fix-traefik-502-bad-gateway)
  • [Fix Traefik SSL Certificate Error](/articles/fix-traefik-ssl-certificate-error)
  • [Fix Traefik Service Not Found](/articles/fix-traefik-service-not-found)