//------------------------------------------------------------------- //-------------------------------------------------------------------
Set Up Traefik with Docker Compose

How to Set Up Traefik with Docker Compose for Self-Hosted Apps and Automatic HTTPS

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:

Type: A
Name: @  (or your subdomain, e.g. whoami)
Value: YOUR_SERVER_IP
TTL: 300

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

dig +short yourdomain.com

Folder Structure

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

/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:

mkdir -p /opt/traefik /opt/apps/whoami
touch /opt/traefik/acme.json
chmod 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:

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:

nano /opt/traefik/docker-compose.yml

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

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=yo**@***il.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:

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

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

apt install apache2-utils -y

Explore key settings in the Traefik Docker Compose file:

SettingWhat It Does
security_opt: no-new-privileges:truePrevents container processes from gaining extra Linux privileges.
providers.docker.exposedbydefault=falseTraefik ignores containers unless they have traefik.enable=true.
providers.docker.network=traefik-proxyTraefik only reads the shared proxy network, not all container networks.
tlschallenge=trueUses TLS-ALPN-01 challenge for certificates (port 443 only, no port 80 needed for cert).
/var/run/docker.sock:roMount as read-only, Traefik only needs to read Docker events.
HTTP → HTTPS redirectAll 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:

cd /opt/traefik
docker compose up -d

Check that it started cleanly with the command below:

docker logs traefik --tail 30

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

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:

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:

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:

cd /opt/apps/whoami
docker compose up -d

Now visit your subdomain:

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:

traefik.enable=true

2. Route requests for this hostname to this container:

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

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

traefik.http.routers.whoami.entrypoints=websecure

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

traefik.http.routers.whoami.tls.certresolver=letsencrypt

5. Forward traffic to port 80 inside the container:

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:

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

In the output, you must see:

issuer: C=US; O=Let's Encrypt

2. Check HTTPS redirect with:

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

You should get 301 Moved Permanently with:

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:

https://traefik.yourdomain.com

4. Check Traefik logs with:

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:

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.

FAQs

Do I need to open any ports for the Traefk whoami app container?

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

What happens when my Traefik SSL certificate expires?

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

Do I need a domain to set up Traefik with Docker Compose?

Yes. Let’s Encrypt requires an accessible domain.

Post Your Comment

PerLod delivers high-performance hosting with real-time support and unmatched reliability.

Contact us

Payment methods

payment gateway