mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2025-12-30 07:40:51 -06:00
- Move Docker healthcheck from Dockerfile to docker-compose files for better environment-specific configuration - Add silent flag to healthcheck curl commands to reduce log noise - Add error handling for missing link_templates table in client view - Improve offline sync date formatting with ISO 8601 conversion helper - Enhance error handlers and profile edit template This improves robustness when migrations haven't been run and provides better date handling in offline sync scenarios.
101 lines
3.4 KiB
YAML
101 lines
3.4 KiB
YAML
services:
|
|
# Certificate generator - runs once to create self-signed certs with SANs
|
|
certgen:
|
|
image: alpine:latest
|
|
container_name: timetracker-certgen-remote
|
|
volumes:
|
|
- ./nginx/ssl:/certs
|
|
- ./scripts:/scripts:ro
|
|
environment:
|
|
- HOST_IP=${HOST_IP:-192.168.1.100}
|
|
command: sh /scripts/generate-certs.sh
|
|
restart: "no"
|
|
|
|
# HTTPS reverse proxy (TLS terminates here)
|
|
nginx:
|
|
image: nginx:alpine
|
|
container_name: timetracker-nginx-remote
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
|
- ./nginx/ssl:/etc/nginx/ssl:ro
|
|
depends_on:
|
|
certgen:
|
|
condition: service_completed_successfully
|
|
app:
|
|
condition: service_started
|
|
restart: unless-stopped
|
|
|
|
app:
|
|
image: ghcr.io/drytrix/timetracker:latest
|
|
container_name: timetracker-app-remote
|
|
environment:
|
|
- TZ=${TZ:-Europe/Brussels}
|
|
- CURRENCY=${CURRENCY:-EUR}
|
|
- ROUNDING_MINUTES=${ROUNDING_MINUTES:-1}
|
|
- SINGLE_ACTIVE_TIMER=${SINGLE_ACTIVE_TIMER:-true}
|
|
- ALLOW_SELF_REGISTER=${ALLOW_SELF_REGISTER:-true}
|
|
- IDLE_TIMEOUT_MINUTES=${IDLE_TIMEOUT_MINUTES:-30}
|
|
- ADMIN_USERNAMES=${ADMIN_USERNAMES:-admin}
|
|
# IMPORTANT: Change SECRET_KEY in production! Used for sessions and CSRF tokens.
|
|
# Generate a secure key: python -c "import secrets; print(secrets.token_hex(32))"
|
|
# The app will refuse to start with the default key in production mode.
|
|
- SECRET_KEY=${SECRET_KEY:-your-secret-key-change-this}
|
|
- DATABASE_URL=postgresql+psycopg2://timetracker:timetracker@db:5432/timetracker
|
|
- LOG_FILE=/app/logs/timetracker.log
|
|
# CSRF and cookies for HTTPS deployments
|
|
- WTF_CSRF_ENABLED=${WTF_CSRF_ENABLED:-true}
|
|
- WTF_CSRF_TIME_LIMIT=${WTF_CSRF_TIME_LIMIT:-3600}
|
|
- WTF_CSRF_SSL_STRICT=${WTF_CSRF_SSL_STRICT:-true}
|
|
- SESSION_COOKIE_SECURE=${SESSION_COOKIE_SECURE:-true}
|
|
- REMEMBER_COOKIE_SECURE=${REMEMBER_COOKIE_SECURE:-true}
|
|
- CSRF_COOKIE_SECURE=${CSRF_COOKIE_SECURE:-true}
|
|
- CSRF_COOKIE_HTTPONLY=${CSRF_COOKIE_HTTPONLY:-false}
|
|
- CSRF_COOKIE_SAMESITE=${CSRF_COOKIE_SAMESITE:-Lax}
|
|
- CSRF_COOKIE_NAME=${CSRF_COOKIE_NAME:-XSRF-TOKEN}
|
|
- PREFERRED_URL_SCHEME=${PREFERRED_URL_SCHEME:-https}
|
|
# Expose only internally; nginx publishes ports
|
|
ports: []
|
|
volumes:
|
|
- app_data_remote:/data
|
|
- app_uploads_remote:/app/app/static/uploads
|
|
- ./logs:/app/logs
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "-s", "-o", "/dev/null", "http://localhost:8080/_health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
|
|
db:
|
|
image: postgres:16-alpine
|
|
container_name: timetracker-db-remote
|
|
environment:
|
|
- POSTGRES_DB=${POSTGRES_DB:-timetracker}
|
|
- POSTGRES_USER=${POSTGRES_USER:-timetracker}
|
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-timetracker}
|
|
- TZ=${TZ:-Europe/Brussels}
|
|
volumes:
|
|
- db_data_remote:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 30s
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
app_data_remote:
|
|
driver: local
|
|
app_uploads_remote:
|
|
driver: local
|
|
db_data_remote:
|
|
driver: local
|