Traefik + Docker: Zero-Config Reverse Proxy That Discovers Your Containers Automatically


Traefik + Docker: Zero-Config Reverse Proxy That Discovers Your Containers Automatically

TL;DR: Traefik watches the Docker socket, auto-discovers new containers, and routes traffic to them based on labels. No config files to edit. No reloads. Just docker compose up and go.


The Nginx Problem

Every time you deploy a new microservice with Nginx, you:

  1. Write an upstream block in nginx.conf
  2. Add a server block with proxy_pass
  3. Run nginx -t to test
  4. Run nginx -s reload to apply
  5. Set up Certbot for SSL
  6. Add a cron job for cert renewal

Multiply this by 10 services and you have 10 config blocks to maintain. Miss one reload and traffic breaks.

Traefik eliminates steps 1-6 entirely.

How Traefik Discovers Docker Containers

Traefik connects to the Docker socket (/var/run/docker.sock) and watches for container events:

Container started → Traefik reads labels → Creates route → Provisions SSL
Container stopped → Traefik removes route → Done
Container scaled → Traefik adds instances to load balancer → Done

No config files. No reloads. No human intervention.

Minimal Setup: 3 Files, 5 Minutes

File 1: traefik.yml

# Static configuration
api:
  dashboard: true
  insecure: true

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

certificatesResolvers:
  letsencrypt:
    acme:
      email: you@example.com
      storage: /acme.json
      httpChallenge:
        entryPoint: web

File 2: docker-compose.yml

version: '3.8'

services:
  traefik:
    image: traefik:v3.1
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/traefik.yml:ro
      - ./acme.json:/acme.json
    networks:
      - web

networks:
  web:
    name: web

File 3: Prepare SSL storage

touch acme.json && chmod 600 acme.json
docker compose up -d

Done. Traefik is running. Dashboard at http://localhost:8080.

Adding Services: Just Labels

Here’s where Traefik shines. To add a new service, you don’t touch Traefik at all. You just add labels to your service’s Docker Compose:

Example: FastAPI Application

# app/docker-compose.yml
version: '3.8'

services:
  fastapi:
    build: .
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.fastapi.rule=Host(`api.mysite.com`)"
      - "traefik.http.routers.fastapi.entrypoints=websecure"
      - "traefik.http.routers.fastapi.tls.certresolver=letsencrypt"
      - "traefik.http.services.fastapi.loadbalancer.server.port=8000"
    networks:
      - web

networks:
  web:
    external: true
docker compose up -d
# Traefik automatically:
# 1. Detects the container
# 2. Creates route for api.mysite.com
# 3. Requests SSL certificate from Let's Encrypt
# 4. Starts routing HTTPS traffic

Example: WordPress

services:
  wordpress:
    image: wordpress:6
    restart: unless-stopped
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wp
      WORDPRESS_DB_PASSWORD: secret
      WORDPRESS_DB_NAME: wordpress
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wordpress.rule=Host(`blog.mysite.com`)"
      - "traefik.http.routers.wordpress.entrypoints=websecure"
      - "traefik.http.routers.wordpress.tls.certresolver=letsencrypt"
      - "traefik.http.services.wordpress.loadbalancer.server.port=80"
    networks:
      - web
      - backend

  db:
    image: mariadb:11
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: rootsecret
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - backend

volumes:
  db_data:

networks:
  web:
    external: true
  backend:

Example: Multiple Services in One Compose

services:
  frontend:
    image: node:20-alpine
    command: npx serve -s build -l 3000
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`mysite.com`)"
      - "traefik.http.routers.frontend.entrypoints=websecure"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
      - "traefik.http.services.frontend.loadbalancer.server.port=3000"
    networks:
      - web

  api:
    build: ./api
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`mysite.com`) && PathPrefix(`/api`)"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      - "traefik.http.services.api.loadbalancer.server.port=8000"
      # Strip /api prefix before forwarding
      - "traefik.http.middlewares.api-strip.stripprefix.prefixes=/api"
      - "traefik.http.routers.api.middlewares=api-strip"
    networks:
      - web

  adminer:
    image: adminer
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.adminer.rule=Host(`db.mysite.com`)"
      - "traefik.http.routers.adminer.entrypoints=websecure"
      - "traefik.http.routers.adminer.tls.certresolver=letsencrypt"
      - "traefik.http.services.adminer.loadbalancer.server.port=8080"
      # Protect with basic auth
      - "traefik.http.middlewares.admin-auth.basicauth.users=admin:$$apr1$$xyz$$hash"
      - "traefik.http.routers.adminer.middlewares=admin-auth"
    networks:
      - web

networks:
  web:
    external: true

Scaling Services

# Scale API to 5 instances
docker compose up -d --scale api=5

# Traefik automatically load-balances across all 5

Check in dashboard (http://localhost:8080) — you’ll see 5 server entries under the API service.

HTTP to HTTPS Redirect

Add global redirect in traefik.yml:

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ":443"

All HTTP traffic automatically redirects to HTTPS. Every service. No per-service config.

Useful Docker Labels Reference

labels:
  # Basic routing
  - "traefik.enable=true"
  - "traefik.http.routers.NAME.rule=Host(`domain.com`)"
  - "traefik.http.routers.NAME.entrypoints=websecure"
  - "traefik.http.routers.NAME.tls.certresolver=letsencrypt"
  - "traefik.http.services.NAME.loadbalancer.server.port=PORT"

  # Path routing
  - "traefik.http.routers.NAME.rule=Host(`domain.com`) && PathPrefix(`/api`)"

  # Strip prefix
  - "traefik.http.middlewares.strip.stripprefix.prefixes=/api"
  - "traefik.http.routers.NAME.middlewares=strip"

  # Basic auth
  - "traefik.http.middlewares.auth.basicauth.users=user:hash"
  - "traefik.http.routers.NAME.middlewares=auth"

  # Rate limiting
  - "traefik.http.middlewares.rate.ratelimit.average=100"
  - "traefik.http.middlewares.rate.ratelimit.burst=50"

  # Health check
  - "traefik.http.services.NAME.loadbalancer.healthcheck.path=/health"
  - "traefik.http.services.NAME.loadbalancer.healthcheck.interval=10s"

  # Sticky sessions
  - "traefik.http.services.NAME.loadbalancer.sticky.cookie=true"

  # Custom headers
  - "traefik.http.middlewares.headers.headers.customResponseHeaders.X-Custom=value"

  # Compression
  - "traefik.http.middlewares.gzip.compress=true"

Debugging

# Check Traefik logs
docker logs traefik -f --tail 50

# Verify container labels
docker inspect <container_id> | jq '.[0].Config.Labels'

# Test routing
curl -H "Host: api.mysite.com" http://localhost

# Check certificate status
curl -vI https://api.mysite.com 2>&1 | grep -A5 "Server certificate"

Summary

Traefik + Docker = reverse proxy that configures itself:

  1. Run Traefik once with Docker socket access
  2. Add labels to any new service
  3. docker compose up -d — traffic routes automatically, SSL provisions automatically
  4. Scale with --scale — load balancing is automatic
  5. No config files to edit. No reloads. No Certbot cron jobs.

One Traefik instance handles all your services. Forever.


Need a custom automation or scraping tool? 79+ production actors on Apify Store. Questions or custom work? Email spinov001@gmail.com

More tips on web scraping, APIs, and Python: https://t.me/scraping_ai