How to Configure Traefik as a Dynamic Reverse Proxy for Docker Containers

Quick Technical Answer:

To configure Traefik v3 as a dynamic Docker reverse proxy: Deploy Traefik via Docker Compose, mounting /var/run/docker.sock and listening on ports 80 and 443. Enable the Docker provider (--providers.docker=true) and ACME resolver. For any application container (e.g. Nextcloud, WordPress, or Node.js), simply attach Docker labels: traefik.enable=true, traefik.http.routers.myapp.rule=Host(`myapp.yourdomain.com`), and traefik.http.routers.myapp.tls.certresolver=myresolver. Traefik auto-discovers the container, routes traffic, and provisions SSL instantly with zero reload downtime.

The Container Orchestration Dilemma: Why Static Proxies Fall Short

In traditional hosting environments, adding a new web service required a tedious manual checklist: spin up the application, find its internal port, open Nginx configuration, write a new location block, test syntax, reload Nginx, and run Certbot.

In containerized Docker environments where microservices, staging builds, and databases dynamically launch, terminate, and scale across internal bridge networks with ephemeral IP addresses, maintaining static Nginx configuration files becomes an administrative nightmare.

Traefik (The Cloud-Native Application Proxy) was engineered specifically for microservices and containers. Traefik listens directly to the Docker socket API. When a new container spins up with Traefik labels, Traefik dynamically registers the route, maps the backend port, generates a Let’s Encrypt TLS certificate, and routes public traffic—without ever touching a configuration file or restarting the proxy daemon.

Step 1: Setting Up the Shared Docker Bridge Network

To allow Traefik to route traffic to independent Docker Compose projects, create a dedicated external bridge network:

# Create shared external network for reverse proxy traffic
docker network create web-gateway

Step 2: Deploying Traefik v3 with Docker Compose

Create a dedicated directory for Traefik and initialize the ACME certificate storage file with strict permissions:

# Create directory and acme.json file
mkdir -p ~/traefik && cd ~/traefik
touch acme.json && chmod 600 acme.json

# Create docker-compose.yml
nano docker-compose.yml

Insert the following production Traefik v3 Compose file:

version: '3.8'

services:
  traefik:
    image: traefik:v3.1
    container_name: traefik
    restart: always
    security_opt:
      - no-new-privileges:true
    networks:
      - web-gateway
    ports:
      - "80:80"
      - "443:443"
    environment:
      - CF_DNS_API_TOKEN=your_optional_cloudflare_token
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./acme.json:/acme.json
    command:
      # API & Dashboard
      - "--api.dashboard=true"
      # EntryPoints
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      # Global HTTP to HTTPS Redirect
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      # Docker Provider Configuration
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=web-gateway"
      # Let's Encrypt TLS Resolver
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@yourdomain.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json"
    labels:
      - "traefik.enable=true"
      # Secure Traefik Dashboard Route
      - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.yourdomain.com`)"
      - "traefik.http.routers.traefik-dashboard.service=api@internal"
      - "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
      - "traefik.http.routers.traefik-dashboard.tls.certresolver=letsencrypt"
      # Basic Auth Protection (Generate with: htpasswd -nb admin password)
      - "traefik.http.routers.traefik-dashboard.middlewares=auth"
      - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz$$encryptedpassword"

networks:
  web-gateway:
    external: true

Launch Traefik:

docker compose up -d

Step 3: Deploying Any Application Behind Traefik in 5 Lines

Now, any container you launch on your server can be instantly exposed with zero proxy configuration. For example, to deploy a Whoami diagnostic test container:

version: '3.8'

services:
  whoami:
    image: traefik/whoami
    container_name: test-app
    restart: always
    networks:
      - web-gateway
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.testapp.rule=Host(`test.yourdomain.com`)"
      - "traefik.http.routers.testapp.entrypoints=websecure"
      - "traefik.http.routers.testapp.tls.certresolver=letsencrypt"
      - "traefik.http.services.testapp.loadbalancer.server.port=80"

networks:
  web-gateway:
    external: true

The moment you execute docker compose up -d on this test service, Traefik automatically notices the new labels, provisions an SSL certificate for test.yourdomain.com, and routes incoming HTTPS traffic directly to port 80 of the container.

Step 4: Architectural Flow & Middleware Pipeline

Traefik processes incoming requests through a clear four-stage pipeline:

  1. EntryPoints: The network listener ports (port 80 HTTP and port 443 HTTPS).
  2. Routers: Match request attributes (Host header, path prefix, or method) and map them to a service.
  3. Middlewares: Modify requests before they reach the backend (e.g. rate limiting, basic authentication, stripping path prefixes, or adding security headers).
  4. Services: Forward requests to healthy backend container IP addresses with integrated health checking.

Frequently Asked Questions (FAQ)

Why does acme.json require permissions 600?

Traefik stores private cryptographic SSL keys inside acme.json. If the file has loose permissions (readable by non-root users), Traefik refuses to launch to protect your server security. Always enforce chmod 600 acme.json.

Can Traefik handle Wildcard SSL certificates?

Yes. To generate wildcard certificates (e.g. *.yourdomain.com), switch the ACME challenge method from tlschallenge to DNS Challenge (using Cloudflare, DigitalOcean, or Namecheap API tokens in environment variables).

Deploy Docker Microservices on CpanelFree Cloud VPS

Scale dynamic container workloads effortlessly with enterprise NVMe storage arrays, dedicated vCPU cores, and root access on CpanelFree.

Explore Cloud VPS Hosting →

Traefik Advanced Production Best Practices & Health Checks

Deploying Traefik in multi-tenant environments requires stringent security policies and resilient circuit-breaker patterns. Implement these architectural safeguards:

  • Docker Socket Hardening: Never mount /var/run/docker.sock with write privileges directly into an internet-exposed container. Instead, route Traefik queries through a read-only socket proxy like tecnativa/docker-socket-proxy, permitting only GET /containers and GET /services API calls.
  • Dynamic Middleware Chaining: Combine rate-limiting, basic authentication, IP whitelisting, and gzip compression into reusable middleware chains defined at the Traefik entrypoint level. This ensures all downstream containers inherit baseline security automatically.
  • Configuring Robust Health Checks: Define explicit service health checks inside the Traefik labels. If a backend web container experiences a worker crash or memory leak, Traefik immediately removes it from the routing pool without dropping client requests:
    - "traefik.http.services.app.loadbalancer.healthcheck.path=/healthz"
    - "traefik.http.services.app.loadbalancer.healthcheck.interval=10s"
    - "traefik.http.services.app.loadbalancer.healthcheck.timeout=3s"
  • Metrics Exporting: Expose Prometheus metrics on a dedicated private port (e.g., :8082/metrics) to visualize request latencies, HTTP error spikes, and active TLS sessions within Grafana dashboards.

Leave a Comment