Traefik
Traefik is a reverse proxy and load balancer that automatically discovers Docker services and configures routing, TLS termination, and middleware dynamically.
This compose file deploys Traefik with HTTP-to-HTTPS redirection, automatic TLS certificate provisioning via a Cloudflare DNS challenge, and Docker provider auto-discovery. The dashboard is protected with HTTP basic authentication. Prometheus metrics, access logging, and health checks are enabled.
For information on setting up basic authentication and IP whitelisting for the Traefik dashboard, check out this blog post.
Docker Compose
# compose.yaml
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
ports:
- 80:80
- 443:443
# - 8080:8080
networks:
- traefik
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- type: volume
source: docker-nfs
target: /certs
volume:
subpath: traefik/certs
security_opt:
- no-new-privileges:true
command:
# EntryPoints
# web - HTTP
- "--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.web.forwardedheaders.trustedips=${TRAEFIK_TRUSTED_IPS}"
# websecure - HTTPS
- "--entrypoints.websecure.address=:443"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.websecure.forwardedheaders.trustedips=${TRAEFIK_TRUSTED_IPS}"
# Disable SSL Verification for self-signed certs
- "--serversTransport.insecureSkipVerify=true"
# DNS Challenge
- "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
- "--certificatesresolvers.cloudflare.acme.email=${CF_API_EMAIL}"
- "--certificatesresolvers.cloudflare.acme.storage=/certs/acme.json"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=traefik"
# Providers file
- "--providers.file.filename=/dynamic/providers.yaml"
# API & Dashboard
- "--api.dashboard=true"
- "--api.insecure=false"
# Observability
- "--log.level=DEBUG"
- "--accesslog=true"
- "--metrics.prometheus=true"
- "--ping=true"
environment:
CF_DNS_API_TOKEN: ${CF_DNS_API_TOKEN}
TZ: Europe/London
labels:
# Enable self‑routing
- "traefik.enable=true"
- "traefik.docker.network=traefik"
# Dashboard router
- "traefik.http.routers.dashboard.rule=Host(`traefik.${TRAEFIK_BASE_URL}`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.tls.certresolver=cloudflare"
# Basic‑auth middleware
- "traefik.http.middlewares.auth.basicauth.users=${BASIC_AUTH_USER_PASS}"
- "traefik.http.routers.dashboard.middlewares=auth@docker"
- "traefik.http.middlewares.auth.basicauth.headerField=X-Remote-User"
# HTTPS headers middleware
- "traefik.http.middlewares.https-header.headers.customrequestheaders.X-Forwarded-Proto=https"
networks:
traefik:
name: traefik
volumes:
docker-nfs:
driver: local
driver_opts:
type: nfs
o: addr=xxx.xxx.xxx.xxx,nolock,soft,rw,nfsvers=4.2
device: :/mnt/nfs-volume
Environment Variables
# .env
CF_API_EMAIL=
CF_DNS_API_TOKEN=
BASIC_AUTH_USER_PASS= # generate with `htpasswd -nb user password`
TRAEFIK_TRUSTED_IPS=
TRAEFIK_BASE_URL=example.com