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

486 lines
8.0 KiB
Markdown

# Docker Deployment Guide
Complete guide for deploying ZynkTime with Docker.
## Quick Start
### 1. Basic Setup
```bash
# 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
```bash
# 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:
```env
# 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):
```yaml
services:
zynktime:
build: .
volumes:
- ./static:/app/static:ro
- ./:/app:ro # Mount source code
environment:
- RELOAD=true
```
**Production Mode** (optimized):
```yaml
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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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:**
```nginx
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:**
```yaml
version: '3.8'
services:
zynktime:
build: .
restart: always
expose:
- "8000"
networks:
- nginx-proxy
networks:
nginx-proxy:
external: true
```
### With Traefik
```yaml
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**
```yaml
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**
```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
```yaml
services:
zynktime:
build: .
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
```
### Scaling
```bash
# Run multiple instances
docker-compose up -d --scale zynktime=3
# With load balancer
docker-compose up -d --scale zynktime=3 nginx
```
## Monitoring
### Health Checks
```bash
# 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
```bash
# Real-time stats
docker stats zynktime
# Detailed info
docker-compose exec zynktime top
```
### Log Management
**Rotate logs:**
```yaml
services:
zynktime:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
```
**Send to external logging:**
```yaml
services:
zynktime:
logging:
driver: "syslog"
options:
syslog-address: "tcp://logs.example.com:514"
```
## Backup and Restore
### Backup Configuration
```bash
# 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
```bash
# 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
```bash
# Check logs
docker-compose logs zynktime
# Check container details
docker inspect zynktime
# Verify environment
docker-compose config
```
### Permission Issues
```bash
# Fix ownership (if needed)
sudo chown -R 1000:1000 ./static ./logs
# Check user inside container
docker-compose exec zynktime id
```
### Network Issues
```bash
# 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
```bash
# 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
```yaml
services:
zynktime:
read_only: true
tmpfs:
- /tmp
```
### 3. Drop Capabilities
```yaml
services:
zynktime:
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
```
### 4. Network Isolation
```yaml
services:
zynktime:
networks:
- internal
# Only expose necessary ports
```
### 5. Secrets Management
```bash
# 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
```dockerfile
# 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
```bash
# 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
```yaml
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
```yaml
deploy:
stage: deploy
script:
- docker-compose build
- docker-compose up -d
only:
- main
```
## Additional Resources
- [Docker Documentation](https://docs.docker.com/)
- [Docker Compose Reference](https://docs.docker.com/compose/)
- [FastAPI Deployment](https://fastapi.tiangolo.com/deployment/)
- [Python Docker Best Practices](https://docs.docker.com/language/python/build-images/)