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:
404 page not foundTraefik dashboard:
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.Missing labels - Required Traefik labels not set
- 2.Wrong label syntax - Incorrect label format
- 3.Docker network - Container not on same network as Traefik
- 4.Service not running - Backend container stopped
- 5.Wrong rule - Host rule doesn't match request
- 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
| Check | Command | Expected |
|---|---|---|
| Labels | docker inspect | traefik.enable=true |
| Network | docker network | Same as Traefik |
| Router | API /api/http/routers | Router exists |
| Service | API /api/http/services | Backend URLs |
| Rule | router.rule | Matches Host |
| Port | loadbalancer.server.port | Correct 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 ```
Related Issues
- [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)