Traefik is a reverse proxy built for containers. It watches Docker, reads labels on your containers and creates routes and HTTPS certificates automatically – no config reload when you add a new app. This guide sets up a Traefik reverse proxy with Docker Compose.
Before you start
- A Linux VPS with Docker Engine and the Compose plugin installed.
- Domains (for example
app.example.com) pointing to the server. - Ports 80 and 443 free – stop any Nginx or Apache on the host.
Create a shared Docker network
docker network create proxyTraefik and every app it serves join this network.
Create the Traefik Compose file
- Make a folder:
mkdir -p ~/traefik && cd ~/traefik && touch acme.json && chmod 600 acme.json. - Create
compose.yaml:services: traefik: image: traefik:v3.1 container_name: traefik restart: unless-stopped command: - --providers.docker=true - --providers.docker.exposedbydefault=false - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.web.http.redirections.entrypoint.scheme=https - --certificatesresolvers.le.acme.email=admin@example.com - --certificatesresolvers.le.acme.storage=/acme.json - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web ports: - 80:80 - 443:443 volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./acme.json:/acme.json networks: - proxy networks: proxy: external: trueUse a current Traefik v3 tag from the official image page.
- Start it:
docker compose up -dand checkdocker logs traefik.
exposedbydefault=false means only containers you label are published.
Publish an app
Example with a simple web container in its own Compose file:
services:
whoami:
image: traefik/whoami
restart: unless-stopped
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`app.example.com`)
- traefik.http.routers.whoami.entrypoints=websecure
- traefik.http.routers.whoami.tls.certresolver=le
- traefik.http.services.whoami.loadbalancer.server.port=80
networks:
- proxy
networks:
proxy:
external: trueRun docker compose up -d. Within a minute Traefik obtains a certificate and https://app.example.com works. Change the server.port label to the port your app listens on inside the container.
Secure the dashboard (optional)
Enable the dashboard only behind authentication. Generate a password hash with htpasswd -nB admin, then add --api.dashboard=true to the command and labels on the Traefik service routing traefik.example.com to api@internal with a basicauth middleware. Escape every $ in the hash as $$ in Compose files.
What to check afterwards
- HTTP requests redirect to HTTPS.
acme.jsoncontains certificates and stays at permission 600.- App containers do not publish their own ports to the host.
Troubleshooting
- 404 page not found: the router rule does not match the host,
traefik.enable=trueis missing, or the container is not on theproxynetwork. - Bad Gateway: wrong
loadbalancer.server.port. - Certificate errors: DNS not pointing to the server, port 80 blocked, or
acme.jsonpermissions too open – checkdocker logs traefik.
Warning: Access to the Docker socket gives root-level control over the host. Mount it read-only as shown, and consider a socket proxy for extra protection.
FAQ: Traefik reverse proxy
Traefik or Nginx for Docker?
Traefik configures itself from container labels, which suits frequently changing stacks. Nginx (or Nginx Proxy Manager) is fine for a few stable apps.
Can Traefik load balance several containers?
Yes. Scale a service with Compose and Traefik balances across all its containers automatically.
Does Traefik support wildcard certificates?
Yes, using the DNS-01 challenge with a supported DNS provider API.
