Files
lego-instructions-manager/docker-compose.yml
T
jessikitty f7c20de5ac Add owner-only logging and Brickset API call tracking
LIM configured no logging at all, so the instruction fetcher had no trail to follow. Adds a rotating file handler on the root logger plus two owner-only admin pages.

- Admin > Logs: filter by level, source and text; tracebacks kept with their error; auto-refresh, raw download, rotated-file browsing and rotate-now

- Admin > Logs > Brickset API calls: every outbound call recorded with method, params, caller, duration, result count and error, plus daily quota accounting (only getSets counts) and a comparison against getKeyUsageStats

- New owner concept (services/ownership.py): a single account, distinct from is_admin, since these pages expose other admins activity. Defaults to the first admin; flask owner show/set to change

- Services now log through module loggers; retention setting and pruning for call records

- New CLI: flask owner show/set, flask logs path/prune

- New table brickset_api_calls, created automatically at boot; LOG_* env vars, /data/logs in Docker
2026-09-27 10:42:49 +10:00

74 lines
2.5 KiB
YAML

# LEGO Instructions Manager - Docker Compose stack
#
# docker compose up -d --build
#
# Configuration lives in .env next to this file (copy .env.docker.example).
# Created by: Jess Rogerson (yelling commands at Claude.AI)
services:
db:
image: postgres:16-alpine
container_name: lim-db
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-lim}
POSTGRES_USER: ${POSTGRES_USER:-lim}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env}
# Keeps index/sort behaviour stable across Postgres upgrades.
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"
volumes:
- lim-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-lim} -d ${POSTGRES_DB:-lim}"]
interval: 10s
timeout: 5s
retries: 10
start_period: 20s
# Not published to the host: only the app container needs to reach it.
expose:
- "5432"
app:
build:
context: .
dockerfile: Dockerfile
image: lim:latest
container_name: lim-app
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
FLASK_APP: run.py
FLASK_ENV: production
SECRET_KEY: ${SECRET_KEY:?SECRET_KEY must be set in .env}
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-lim}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB:-lim}
UPLOAD_FOLDER: /data/uploads
BACKUP_FOLDER: /data/backups
BACKUP_KEEP: ${BACKUP_KEEP:-7}
MAX_CONTENT_LENGTH: ${MAX_CONTENT_LENGTH:-52428800}
SETS_PER_PAGE: ${SETS_PER_PAGE:-20}
BRICKSET_API_KEY: ${BRICKSET_API_KEY:-}
BRICKSET_USERNAME: ${BRICKSET_USERNAME:-}
BRICKSET_PASSWORD: ${BRICKSET_PASSWORD:-}
# Automatic instruction fetcher. Safe to leave on: gunicorn runs a
# single worker here, so there is exactly one ticker, and it does
# nothing until an admin enables it in the UI.
LOG_FOLDER: /data/logs
LOG_LEVEL: ${LOG_LEVEL:-INFO}
LOG_MAX_BYTES: ${LOG_MAX_BYTES:-2097152}
LOG_BACKUP_COUNT: ${LOG_BACKUP_COUNT:-5}
LOG_ACCESS: ${LOG_ACCESS:-0}
INSTRUCTION_FETCH_WORKER: ${INSTRUCTION_FETCH_WORKER:-1}
INSTRUCTION_FETCH_TICK_SECONDS: ${INSTRUCTION_FETCH_TICK_SECONDS:-20}
FETCH_MAX_FILE_MB: ${FETCH_MAX_FILE_MB:-150}
FETCH_TIMEOUT_SECONDS: ${FETCH_TIMEOUT_SECONDS:-60}
volumes:
- lim-data:/data
ports:
- "${LIM_PORT:-8000}:8000"
volumes:
lim-db:
lim-data: