← Back to documentation

Installing Docker and Setting up Traefik

Complete guide to install Docker, Docker Compose, and deploy Traefik reverse proxy with example services

dockertraefikreverse-proxycontainersssl

Introduction

Docker simplifies application deployment by using containers. This guide will walk you through installing Docker, setting up Traefik as a reverse proxy, and deploying your first containerized application.

Traefik is a modern reverse proxy that automatically handles SSL certificates and service discovery for your Docker containers.

Prerequisites

  • A VPS with Ubuntu 24.04 or newer
  • Root or sudo access
  • A domain name pointed to your server (for SSL)
  • Basic command-line knowledge

Step 1: Install Docker

Remove Old Versions

First, remove any old Docker installations:

sudo apt remove docker docker-engine docker.io containerd runc

Install Dependencies

sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

Add Docker’s Official GPG Key

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Set Up the Repository

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Install Docker Engine

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io

Verify Installation

sudo docker --version
sudo docker run hello-world

You should see a “Hello from Docker!” message.

Step 2: Install Docker Compose Plugin

Docker Compose makes it easy to manage multi-container applications. We’ll use the Docker Compose plugin (v2), which is the modern, recommended approach.

Install Docker Compose Plugin

sudo apt install -y docker-compose-plugin

Verify Installation

docker compose version

Note: The command is docker compose (with a space), not docker-compose (with a hyphen).

Step 3: Configure Docker for Non-Root User

Running Docker as root is not recommended. Let’s add your user to the docker group:

sudo usermod -aG docker $USER

Log out and back in for this to take effect, or run:

newgrp docker

Test without sudo:

docker ps

Step 4: Create Docker Network

Create a dedicated network for Traefik:

docker network create traefik-public

Step 5: Set Up Traefik

Create Directory Structure

mkdir -p ~/traefik
cd ~/traefik

Create Traefik Configuration

Create traefik.yml:

nano traefik.yml

Add the following configuration:

api:
  dashboard: true
  insecure: false

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt:
    acme:
      email: your-email@example.com
      storage: /letsencrypt/acme.json
      httpChallenge:
        entryPoint: web

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: traefik-public

Replace your-email@example.com with your actual email.

Create Docker Compose File

Create docker-compose.yml:

nano docker-compose.yml

Add:

services:
  traefik:
    image: traefik:v2.10
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - traefik-public
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/traefik.yml:ro
      - ./letsencrypt:/letsencrypt
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.your-domain.com`)"
      - "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
      - "traefik.http.routers.traefik-dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik-dashboard.service=api@internal"
      - "traefik.http.routers.traefik-dashboard.middlewares=auth"
      - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$8EVjn/nj$$GiLUZqcbueTFeD23SuB6x0"

networks:
  traefik-public:
    external: true

Replace traefik.your-domain.com with your actual domain.

Note: The password hash in the example is for the password “changeme”. You should generate your own using:

echo $(htpasswd -nb admin your-password) | sed 's/\$/\$\$/g'

Install htpasswd if needed: sudo apt install apache2-utils

Create Let’s Encrypt Directory

mkdir letsencrypt
chmod 600 letsencrypt

Start Traefik

docker compose up -d

Check Status

docker compose ps
docker compose logs -f traefik

Step 6: Deploy Whoami Example

Now let’s deploy a simple whoami service to test Traefik.

Create Project Directory

mkdir -p ~/whoami
cd ~/whoami

Create Docker Compose File

nano docker-compose.yml

Add:

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

networks:
  traefik-public:
    external: true

Replace whoami.your-domain.com with your subdomain.

Start Whoami Service

docker compose up -d

Test Your Service

Test with curl:

curl https://whoami.your-domain.com

You should see output similar to:

Hostname: whoami
IP: 172.19.0.3
RemoteAddr: 172.19.0.2:54321
GET / HTTP/1.1
Host: whoami.your-domain.com
User-Agent: curl/7.81.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 123.45.67.89
X-Forwarded-Host: whoami.your-domain.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: traefik
X-Real-Ip: 123.45.67.89

This confirms Traefik is correctly routing traffic and automatically handling SSL.

Adding More Services

To add more services behind Traefik, follow this pattern:

services:
  my-app:
    image: my-app-image:latest
    container_name: my-app
    restart: unless-stopped
    networks:
      - traefik-public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.my-app.rule=Host(`app.your-domain.com`)"
      - "traefik.http.routers.my-app.entrypoints=websecure"
      - "traefik.http.routers.my-app.tls.certresolver=letsencrypt"
      - "traefik.http.services.my-app.loadbalancer.server.port=8080"

networks:
  traefik-public:
    external: true

Key points:

  • traefik.enable=true - Enables Traefik routing
  • Host() - Your domain/subdomain
  • entrypoints=websecure - Uses HTTPS
  • certresolver=letsencrypt - Auto SSL certificate
  • loadbalancer.server.port - Internal container port

Updating Containers

To update a container to the latest version:

cd ~/whoami  # or your service directory
docker compose pull
docker compose up -d

Traefik will automatically handle SSL certificates and routing during updates.

Performance Optimization

Limit Container Resources

Add to your service in docker-compose.yml:

services:
  my-app:
    # ... other config
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

Enable Docker Logging Rotation

Edit /etc/docker/daemon.json:

sudo nano /etc/docker/daemon.json

Add:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Restart Docker:

sudo systemctl restart docker

Need Help?

Having issues with Docker or Traefik?

Happy containerizing! 🐳