How to Set Up Traefik with Docker Compose and Automatic HTTPS

Updated on Aug 18, 2026
Kimberly N
7 MINS READ
Table of Contents
Set Up Traefik with Docker Compose

If you run self-hosted apps and want HTTPS without the complexity, learning how to set up Traefik with Docker Compose is one of the best things you can do for your stack. Traefik acts as a reverse proxy that sits in front of your containers, handles routing by reading Docker labels, and automatically gets free SSL certificates from Let's Encrypt.

This guide will show you how to set up Traefik with Docker Compose on Ubuntu, and you will get automatic HTTPS, proper folder structure, a working sample app, and basic hardening, all without Kubernetes.

Prerequisites to Set Up Traefik with Docker Compose

Before you begin to set up Traefik with Docker Compose, make sure to prepare these prerequisites:

  • A Linux VPS or dedicated server running Ubuntu 22.04 or 24.04. You can easily deploy your reverse proxy stack on a PerLod Linux VPS.
  • Docker and Docker Compose are installed. A public domain name with DNS access.
  • Ports 80 and 443 are open on your server's firewall.
  • An email address for Let's Encrypt registration.

DNS Setup

Before Traefik can get a certificate, your domain must point to your server's IP. If you don't have a Domain, you can register a Domain on PerLod.

You can create an A record like this in your DNS panel:

HTML/XML
Type: AName: @  (or your subdomain, e.g. whoami)Value: YOUR_SERVER_IPTTL: 300

Let DNS propagate before running Traefik. You can verify it with:

Bash
dig +short yourdomain.com

Folder Structure

It is better to keep things clean and organized. Here is the folder layout used in this guide:

HTML/XML
/opt/traefik/├── docker-compose.yml├── acme.json└── data/    └── traefik.yml    # (optional static config file) /opt/apps/└── whoami/    └── docker-compose.yml

Run this to create the required folders and permissions for Traefik:

Bash
mkdir -p /opt/traefik /opt/apps/whoamitouch /opt/traefik/acme.jsonchmod 600 /opt/traefik/acme.json

Remember to set the correct permission; Traefik will refuse to start if acme.json has loose permissions.

Once you are done with these prerequisites, you can proceed to the following steps to set up Traefik with Docker Compose.

Step 1: Create the Shared Docker Network

Traefik needs to communicate with your app containers. You must create a shared external network that all services will join:

Bash
docker network create traefik-proxy

All containers that Traefik should route to must be on this network.

Step 2: Set Up Traefik with Docker Compose

This is the core step where you set up Traefik with Docker Compose for the first time. Use the command below to create the Traefik compose file:

Bash
nano /opt/traefik/docker-compose.yml

Paste the following content into the file with your actual email and with your real domain:

YAML
networks:  traefik-proxy:    external: true services:  traefik:    image: traefik:v3.7    container_name: traefik    restart: unless-stopped    security_opt:      - no-new-privileges:true    command:      - --api.dashboard=true      - --log.level=INFO      - --accesslog=true      - --providers.docker=true      - --providers.docker.exposedbydefault=false      - --providers.docker.network=traefik-proxy      - --entrypoints.web.address=:80      - --entrypoints.web.http.redirections.entrypoint.to=websecure      - --entrypoints.web.http.redirections.entrypoint.scheme=https      - --entrypoints.websecure.address=:443      - --certificatesresolvers.letsencrypt.acme.email=your@email.com      - --certificatesresolvers.letsencrypt.acme.storage=/acme.json      - --certificatesresolvers.letsencrypt.acme.tlschallenge=true    ports:      - "80:80"      - "443:443"    volumes:      - /var/run/docker.sock:/var/run/docker.sock:ro      - /opt/traefik/acme.json:/acme.json    networks:      - traefik-proxy    labels:      - traefik.enable=true      - traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)      - traefik.http.routers.dashboard.entrypoints=websecure      - traefik.http.routers.dashboard.tls.certresolver=letsencrypt      - traefik.http.routers.dashboard.service=api@internal      - traefik.http.routers.dashboard.middlewares=dashboard-auth      - traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$apr1$$REPLACE_THIS_HASH

You can use the command below to generate the password hash and then replace it in the above config. Remember to double every $ sign when pasting into a compose file:

Bash
echo $(htpasswd -nbB admin "YourSecurePassword") | sed -e s/\\$/\\$\\$/g

If you need Apache utils, you can install them first:

Bash
apt install apache2-utils -y

Explore key settings in the Traefik Docker Compose file:

Setting What It Does
security_opt: no-new-privileges:true Prevents container processes from gaining extra Linux privileges.
providers.docker.exposedbydefault=false Traefik ignores containers unless they have traefik.enable=true.
providers.docker.network=traefik-proxy Traefik only reads the shared proxy network, not all container networks.
tlschallenge=true Uses TLS-ALPN-01 challenge for certificates (port 443 only, no port 80 needed for cert).
/var/run/docker.sock:ro Mount as read-only, Traefik only needs to read Docker events.
HTTP → HTTPS redirect All port 80 traffic automatically redirects to 443.

Step 3: Start Traefik

Once you are finished creating the Docker Compose, you can use the command below to bring up the Traefik stack:

Bash
cd /opt/traefikdocker compose up -d

Check that it started cleanly with the command below:

Bash
docker logs traefik --tail 30

You should see lines like Configuration loaded from flags and no errors. After 30 to 60 seconds, visit:

HTML/XML
https://traefik.yourdomain.com

You should get a login prompt for the dashboard.

Step 4: Deploy a Sample App with Traefik Whoami

Now you will see why it is so easy to set up Traefik with Docker Compose for multiple apps. Each new app just needs Docker labels and no Traefik config edits required.

For example, create the whoami app compose file with the command below:

Bash
nano /opt/apps/whoami/docker-compose.yml

Add the following content with your actual subdomain and make sure its A record points to your server IP:

YAML
networks:  traefik-proxy:    external: true services:  whoami:    image: traefik/whoami    container_name: whoami    restart: unless-stopped    expose:      - "80"    networks:      - traefik-proxy    labels:      - traefik.enable=true      - traefik.http.routers.whoami.rule=Host(`whoami.yourdomain.com`)      - traefik.http.routers.whoami.entrypoints=websecure      - traefik.http.routers.whoami.tls.certresolver=letsencrypt      - traefik.http.services.whoami.loadbalancer.server.port=80

Start it with the commands below:

Bash
cd /opt/apps/whoamidocker compose up -d

Now visit your subdomain:

HTML/XML
https://whoami.yourdomain.com

Traefik will request a certificate automatically, and you will see the whoami output with your request headers.

How Docker Labels Work for Traefik

When you set up Traefik with Docker Compose, each label tells Traefik something specific about how to route traffic. Here are the labels and what they do:

1. Tell Traefik to watch this container:

HTML/XML
traefik.enable=true

2. Route requests for this hostname to this container:

HTML/XML
traefik.http.routers.whoami.rule=Host(`whoami.yourdomain.com`)

3. Only accept traffic on the HTTPS entrypoint port 443:

HTML/XML
traefik.http.routers.whoami.entrypoints=websecure

4. Use Let's Encrypt to get and renew the certificate automatically:

HTML/XML
traefik.http.routers.whoami.tls.certresolver=letsencrypt

5. Forward traffic to port 80 inside the container:

HTML/XML
traefik.http.services.whoami.loadbalancer.server.port=80

Note: You do not publish ports on the app container; only Traefik exposes ports 80 and 443. App containers expose only their ports for internal Docker networking.

Verify Your Traefik Setup with Docker Compose

When you are finished setting up Traefik with Docker Compose, you must verify everything works correctly.

1. Check the certificate with the command below:

Bash
curl -v https://whoami.yourdomain.com 2>&1 | grep -i "SSL\|certificate\|issuer"

In the output, you must see:

HTML/XML
issuer: C=US; O=Let's Encrypt

2. Check HTTPS redirect with:

Bash
curl -I http://whoami.yourdomain.com

You should get 301 Moved Permanently with:

HTML/XML
Location: https://whoami.yourdomain.com

3. Check Traefik dashboard:

Open the following URL in your browser, log in with the credentials you set up, and you should see your routers and services listed under the HTTP section:

HTML/XML
https://traefik.yourdomain.com

4. Check Traefik logs with:

Bash
docker logs traefik --follow

Look for any level=error lines. A healthy setup shows only level=info or level=debug messages.

Basic Hardening Tips To Set Up Traefik with Docker Compose for Production

When you set up Traefik with Docker Compose for production, these hardening steps matter a lot:

  • Never expose port 8080: This is the insecure dashboard port. This guide routes the dashboard through HTTPS with basic auth instead.
  • Mount the Docker socket as read-only, :ro at the end of the volume line: Traefik only needs to watch events, not control Docker.
  • Use security_opt: no-new-privileges:true: Stops container processes from escalating privileges.
  • Set exposedbydefault=false: Prevents accidentally exposing containers without labels.
  • Keep Traefik updated: The project releases security patches regularly. Pin to a minor version like traefik:v3.7 and update on new releases.
  • Use strong passwords for basic auth and consider replacing it with an SSO solution like Authentik or Authelia for the dashboard.
  • Enable access logs: The --accesslog=true gives you visibility into all traffic hitting your proxy.

How To Add More Apps to Traefik

The power of this setup is that adding a new self-hosted app is just a matter of joining it to the Traefik Proxy network and adding the right labels. Here is the template for any new service:

YAML
networks:  traefik-proxy:    external: true services:  myapp:    image: myapp:latest    container_name: myapp    restart: unless-stopped    expose:      - "3000"   # the port your app listens on internally    networks:      - traefik-proxy    labels:      - traefik.enable=true      - traefik.http.routers.myapp.rule=Host(`myapp.yourdomain.com`)      - traefik.http.routers.myapp.entrypoints=websecure      - traefik.http.routers.myapp.tls.certresolver=letsencrypt      - traefik.http.services.myapp.loadbalancer.server.port=3000

Note: No changes to the Traefik container needed; it detects new containers automatically.

Conclusion

With Traefik Docker Compose setup, you get automatic HTTPS and dynamic routing through Docker labels, all without touching Nginx configs or managing certificates manually. Once the traefik-proxy network is ready and Traefik is running, adding a new app takes less than a minute.

We hope you enjoy this guide. To see all Docker labels and providers, you can check the official Traefik Docker Provider Documentation.

 

No. Only Traefik needs ports 80 and 443 exposed. App containers only use expose: which is internal to Docker.

Nothing, Traefik renews Let's Encrypt certificates automatically before they expire. No action needed on your part.

Yes. Let's Encrypt requires an accessible domain.