Skip to main content

Kimai - Docker Compose Stack, Traefik Reverse Proxy

425 words·
Kimai MySQL Docker-Compose Traefik
Table of Contents

Docker Compose stack for the Kimai time-tracking application.

Kimai Docker Compose Deployment
#

Folder Structure
#

# Create folder structure
sudo mkdir -p /opt/kimai && cd /opt/kimai

Environment File
#

# Create .env file
sudo vi .env
# .env
MYSQL_PW=kimai-pw
MYSQL_ROOT_PW=sql-root-pw

Docker Compose
#

# Create Docker Compose file
sudo vi docker-compose.yml

HTTP Version
#

version: "3.9"
services:

  app:
    container_name: kimai
    image: kimai/kimai2:apache
    ports:
      - "80:8001"
    depends_on:
        - db
    environment:
      - DATABASE_URL=mysql://kimai:${MYSQL_PW}@db:3306/kimai
      - TRUSTED_HOSTS=localhost,kimai.jklug.work
    volumes:
      - ./public:/opt/kimai/public
    restart: unless-stopped

  db:
    image: mysql:8
    container_name: db
    environment:
      - MYSQL_DATABASE=kimai
      - MYSQL_USER=kimai
      - MYSQL_PASSWORD=${MYSQL_PW}
      - MYSQL_ROOT_PASSWORD={$MYSQL_ROOT_PW}
    volumes:
      - ./mysql:/var/lib/mysql
    restart: unless-stopped

Traefik Reverse Proxy Version
#

version: "3.9"
services:

  app:
    container_name: kimai
    image: kimai/kimai2:apache
    ports:
      - "8001"
    depends_on:
        - db
    environment:
      - DATABASE_URL=mysql://kimai:${MYSQL_PW}@db:3306/kimai
      - TRUSTED_HOSTS=localhost,kimai.jklug.work
    volumes:
      - ./public:/opt/kimai/public
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik"
      - "traefik.http.services.kimai-service.loadbalancer.server.port=8001"
      # HTTPS Router
      - "traefik.http.routers.kimai.entrypoints=websecure"
      - "traefik.http.routers.kimai.tls=true"
      - "traefik.http.routers.kimai.rule=Host(`kimai.jklug.work`)"
      # HTTP Router
      - "traefik.http.routers.kimai-http.rule=Host(`kimai.jklug.work`)"
      - "traefik.http.routers.kimai-http.entrypoints=web"
      - "traefik.http.routers.kimai-http.middlewares=redirect-to-https"
      # Middleware for HTTP to HTTPS redirection
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
    networks:
      - intern
      - traefik

  db:
    image: mysql:8
    container_name: db
    environment:
      - MYSQL_DATABASE=kimai
      - MYSQL_USER=kimai
      - MYSQL_PASSWORD=${MYSQL_PW}
      - MYSQL_ROOT_PASSWORD={$MYSQL_ROOT_PW}
    volumes:
      - ./mysql:/var/lib/mysql
    restart: unless-stopped
    labels:
      - "traefik.enable = false"
    networks:
      - intern

networks:
  traefik:
    external: true
  intern:

Start Container
#

# Create / start Docker container
sudo docker compose up -d

Create Admin User
#

# Create admin user: Define username & email
sudo docker exec -ti kimai \
    /opt/kimai/bin/console kimai:user:create admin admin@example.com ROLE_SUPER_ADMIN

# Shell output:
Please enter the password: # Define admin pw

Webinterface
#

# HTTP Version
192.168.30.92:80

# Reverse Proxy Version
kimai.jklug.work

Traefik Reverse Proxy
#

For the following Traefik reverse proxy setup I use a Let’s Encrypt wildcard certificate.

Docker Network
#

# Create a reverse proxy network
sudo docker network create traefik

Folder Structure
#

# Create folder structure
sudo mkdir -p /opt/traefik/certs && cd /opt/traefik/

Docker Compose
#

# Create Docker Compose file
sudo vi docker-compose.yml

version: '3'
services:
  reverse-proxy:
    image: traefik:v2.10
    container_name: Traefik-Reverse-Proxy
    restart: unless-stopped
    command:
      - --api.insecure=true
      - --providers.docker
      - --providers.file.directory=/etc/traefik/dynamic
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./tls-configuration.yaml:/etc/traefik/dynamic/tls-configuration.yaml
      - ./certs/:/etc/certs/
    networks:
      - traefik

networks:
  traefik:
    external: true

Traefik Dynamic Configuration
#

# Create file for dynamic configuration
sudo vi tls-configuration.yaml
# tls-configuration.yaml
tls:
  certificates:
    - certFile: /etc/certs/fullchain.pem
      keyFile: /etc/certs/privkey.pem

Note: The Let’s Encrypt wildcard certificates fullchain.pem & privkey.pem must be placed inside the /opt/traefik/certificates directory before the Docker stack is started.


Start Docker Compose Container
#

# Start Docker Compose Container
sudo docker compose up -d

Links #

# Official Documentation
https://www.kimai.org/documentation/docker.html

# Official Documentation
https://www.kimai.org/documentation/docker-compose.html