Files
2025-12-02 21:26:08 +01:00

8.0 KiB

Docker Deployment Guide

Complete guide for deploying ZynkTime with Docker.

Quick Start

1. Basic Setup

# Clone and navigate to project
cd zynktime

# Create environment file
cp .env.example .env

# Edit with your API key
nano .env

# Start the application
docker-compose up -d

# Access at http://localhost:8000

2. Verify Deployment

# Check container status
docker-compose ps

# View logs
docker-compose logs -f

# Test health endpoint
curl http://localhost:8000/health

Configuration

Environment Variables

Edit .env file:

# Required
KLEER_API_KEY=your_actual_api_key_here

# Optional (with defaults)
KLEER_USERNAME=Christopher Juhlin
KLEER_COMPANY_ID=1336

Docker Compose Options

Development Mode (with live reload):

services:
  zynktime:
    build: .
    volumes:
      - ./static:/app/static:ro
      - ./:/app:ro  # Mount source code
    environment:
      - RELOAD=true

Production Mode (optimized):

services:
  zynktime:
    image: zynktime:1.0.0
    restart: always
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL

Common Operations

Starting and Stopping

# Start in background
docker-compose up -d

# Start in foreground (see logs)
docker-compose up

# Stop containers
docker-compose down

# Stop and remove volumes
docker-compose down -v

Viewing Logs

# Follow all logs
docker-compose logs -f

# Last 100 lines
docker-compose logs --tail=100

# Specific service logs
docker-compose logs -f zynktime

Updating the Application

# Pull latest code
git pull

# Rebuild and restart
docker-compose up -d --build

# Or force recreate
docker-compose up -d --force-recreate

Accessing the Container

# Open bash shell
docker-compose exec zynktime bash

# Run CLI mode
docker-compose exec zynktime python main.py cli

# Run tests
docker-compose exec zynktime pytest -v

Production Deployment

With Nginx Reverse Proxy

nginx.conf:

server {
    listen 80;
    server_name time.yourdomain.com;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

docker-compose.yml:

version: '3.8'

services:
  zynktime:
    build: .
    restart: always
    expose:
      - "8000"
    networks:
      - nginx-proxy

networks:
  nginx-proxy:
    external: true

With Traefik

version: '3.8'

services:
  zynktime:
    build: .
    restart: always
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.zynktime.rule=Host(`time.example.com`)"
      - "traefik.http.routers.zynktime.entrypoints=websecure"
      - "traefik.http.routers.zynktime.tls.certresolver=letsencrypt"
      - "traefik.http.services.zynktime.loadbalancer.server.port=8000"

networks:
  traefik:
    external: true

SSL/HTTPS Setup

Option 1: Let's Encrypt with Traefik

services:
  traefik:
    image: traefik:v2.9
    command:
      - "[email protected]"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"

Option 2: Manual SSL with Nginx

server {
    listen 443 ssl http2;
    server_name time.yourdomain.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:8000;
    }
}

Resource Management

Memory and CPU Limits

services:
  zynktime:
    build: .
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

Scaling

# Run multiple instances
docker-compose up -d --scale zynktime=3

# With load balancer
docker-compose up -d --scale zynktime=3 nginx

Monitoring

Health Checks

# Check health status
docker inspect zynktime | jq '.[0].State.Health'

# Watch health status
watch -n 5 'docker inspect zynktime | jq ".[0].State.Health"'

Resource Usage

# Real-time stats
docker stats zynktime

# Detailed info
docker-compose exec zynktime top

Log Management

Rotate logs:

services:
  zynktime:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Send to external logging:

services:
  zynktime:
    logging:
      driver: "syslog"
      options:
        syslog-address: "tcp://logs.example.com:514"

Backup and Restore

Backup Configuration

# Backup .env file
cp .env .env.backup

# Backup logs (if using volume)
docker-compose exec zynktime tar -czf /tmp/logs.tar.gz /app/logs
docker cp zynktime:/tmp/logs.tar.gz ./logs-backup.tar.gz

Disaster Recovery

# Export container
docker commit zynktime zynktime-backup:$(date +%Y%m%d)
docker save zynktime-backup:latest | gzip > zynktime-backup.tar.gz

# Restore from backup
docker load < zynktime-backup.tar.gz
docker-compose up -d

Troubleshooting

Container Won't Start

# Check logs
docker-compose logs zynktime

# Check container details
docker inspect zynktime

# Verify environment
docker-compose config

Permission Issues

# Fix ownership (if needed)
sudo chown -R 1000:1000 ./static ./logs

# Check user inside container
docker-compose exec zynktime id

Network Issues

# Test connectivity
docker-compose exec zynktime curl http://localhost:8000/health

# Check network
docker network inspect zynktime-network

# Recreate network
docker-compose down
docker network prune
docker-compose up -d

API Key Issues

# Verify environment variables
docker-compose exec zynktime env | grep KLEER

# Test API connection
docker-compose exec zynktime python -c "from config import Config; Config.validate_config()"

Security Best Practices

1. Run as Non-Root User

Already configured in Dockerfile (user: zynktime, UID: 1000)

2. Read-Only Filesystem

services:
  zynktime:
    read_only: true
    tmpfs:
      - /tmp

3. Drop Capabilities

services:
  zynktime:
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

4. Network Isolation

services:
  zynktime:
    networks:
      - internal
    # Only expose necessary ports

5. Secrets Management

# Use Docker secrets instead of .env
echo "my_api_key" | docker secret create kleer_api_key -

# In compose file:
services:
  zynktime:
    secrets:
      - kleer_api_key

Performance Optimization

Image Size Optimization

# Multi-stage build
FROM python:3.11-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

FROM python:3.11-slim
COPY --from=builder /root/.local /root/.local
COPY . /app

Caching Strategies

# Use BuildKit for better caching
DOCKER_BUILDKIT=1 docker-compose build

# Cache requirements separately
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

CI/CD Integration

GitHub Actions

name: Build and Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build and push
        run: |
          docker build -t zynktime:latest .
          docker-compose up -d

GitLab CI

deploy:
  stage: deploy
  script:
    - docker-compose build
    - docker-compose up -d
  only:
    - main

Additional Resources