How to Set Up Traefik and Portainer on Ubuntu with Docker Compose
Updated June 2026 — commands and versions refreshed for current releases. Ubuntu 18.04 reached end of life, so this guide targets Ubuntu 24.04 LTS, and the config is updated for Traefik v3 and current Portainer CE.
Overview
This tutorial explains how to set up Traefik (a reverse proxy and load balancer) alongside Portainer (a Docker management tool) using Docker Compose. The original article used Ubuntu 18.04, which is now end of life; these steps target Ubuntu 24.04 LTS. The setup lets you host multiple applications on a single server with automatic traffic routing, Let's Encrypt SSL, and container management.
Key Components

Traefik provides dynamic routing, load balancing, automatic Let's Encrypt SSL certificate management, and a dashboard for monitoring entrypoints and services.
Portainer is a powerful, open-source management toolset that lets you build, manage, and maintain Docker environments from a web UI.
Prerequisites
- Docker and Docker Compose installed
- DNS entries pointing your subdomains (for example traefik.example.com and portainer.example.com) to your server's IP
- The directory structure below created
Install Docker
The legacy apt-key method is deprecated. Install Docker Engine and the Compose plugin using Docker's current keyring-based repository:
$ sudo apt-get update
$ sudo apt-get install ca-certificates curl gnupg
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
$ sudo docker run hello-world
$ sudo usermod -aG docker ${USER}
$ sudo reboot
Docker Compose is now bundled as a plugin, so the command is docker compose (with a space). The standalone docker-compose binary download from the original article is no longer needed.
Directory Structure
Create a working directory for the core stack:
/home/ubuntu/docker/core/
├── docker-compose.yml
├── traefik-data/
│ ├── acme.json
│ └── traefik.yml
└── portainer-data/
mkdir -p /home/ubuntu/docker/core/traefik-data
mkdir -p /home/ubuntu/docker/core/portainer-data
touch /home/ubuntu/docker/core/traefik-data/acme.json
chmod 600 /home/ubuntu/docker/core/traefik-data/acme.json
touch /home/ubuntu/docker/core/traefik-data/traefik.yml
Traefik Static Configuration (traefik.yml)
This is the v3 static config. The provider and ACME blocks are largely the same as v2, but note Traefik v3 renamed the entrypoint-redirect mechanism and tightened a few label names.
api:
dashboard: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
http:
acme:
email: [email protected]
storage: acme.json
httpChallenge:
entryPoint: http
Replace the email address with your own so Let's Encrypt can send expiry notices.
Generate a Secure Dashboard Password
$ sudo apt install apache2-utils
$ echo $(htpasswd -nb <username> <password>) | sed -e s/\$/\$\$/g
Replace <username> and <password> with your credentials, then paste the escaped result into the basicauth label below.
Create the Docker Network
docker network create traefik-proxy
Docker Compose File
The top-level version: key is obsolete in modern Compose and can be omitted. Traefik is pinned to v3 and Portainer to the current Community Edition image.
services:
traefik:
image: traefik:v3.4
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- traefik-proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik-data/traefik.yml:/traefik.yml:ro
- ./traefik-data/acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=http"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
- "traefik.http.middlewares.traefik-auth.basicauth.users=username:password"
- "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
- "traefik.http.routers.traefik-secure.entrypoints=https"
- "traefik.http.routers.traefik-secure.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
- "traefik.http.routers.traefik-secure.tls=true"
- "traefik.http.routers.traefik-secure.tls.certresolver=http"
- "traefik.http.routers.traefik-secure.service=api@internal"
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- traefik-proxy
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./portainer-data:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.portainer.entrypoints=http"
- "traefik.http.routers.portainer.rule=Host(`portainer.example.com`)"
- "traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.portainer.middlewares=portainer-https-redirect"
- "traefik.http.routers.portainer-secure.entrypoints=https"
- "traefik.http.routers.portainer-secure.rule=Host(`portainer.example.com`)"
- "traefik.http.routers.portainer-secure.tls=true"
- "traefik.http.routers.portainer-secure.tls.certresolver=http"
- "traefik.http.routers.portainer-secure.service=portainer"
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
- "traefik.docker.network=traefik-proxy"
networks:
traefik-proxy:
external: true
Note the original image was portainer/portainer; the current image is portainer/portainer-ce. Update the domain names and credentials to match your environment.
Deploy the Services
docker compose up -d
Once the containers are healthy, access the services at:
- https://traefik.example.com — the Traefik dashboard (behind basic auth)
- https://portainer.example.com — the Portainer UI (set your admin password on first visit)
Useful Commands
docker compose up # run in the foreground to watch logs on first run
docker compose logs # check logs
docker compose ps # view container status
You now have an auto-SSL reverse proxy fronting a Docker management UI, ready to route any additional service you add to the traefik-proxy network.
Indivar Software Solutions
SAP Business One consulting and custom software development since 2009. Offices in India, New Zealand, and the USA.