services: app: # Published multi-arch image (linux/amd64 + linux/arm64). In a repo # clone, docker-compose.override.yml sits next to this file and builds # this same tag from source instead. image: ghcr.io/lucifix/model-workshop-manager:${APP_IMAGE_TAG:-latest} restart: unless-stopped # Runs unprivileged. Defaults to the image's own `node` user (uid 1000), # which owns /data and /backups inside the image — so a named volume just # works. Override both when WORKSHOP_DATA_DIR or BACKUP_DIR is a bind # mount, to whatever uid:gid owns that directory on the host # (`stat -c '%u:%g' /your/path`). user: "${APP_UID:-1000}:${APP_GID:-1000}" labels: - docker-volume-backup.stop-during-backup=workshop environment: NODE_ENV: production PORT: ${APP_PORT:-3000} DATABASE_URL: /data/database/workshop.db DATA_DIR: /data UPLOAD_DIR: /data/uploads BACKUP_DIR: /backups UPCITEMDB_ENABLED: ${UPCITEMDB_ENABLED:-false} # Optional — only used to auto-create the login on a fresh install's # first boot, or to migrate an existing deployment's credentials into # the database. Unset on a fresh install and use the setup screen # instead; safe to remove from .env once a credential exists either way. AUTH_USERNAME: ${AUTH_USERNAME:-} AUTH_PASSWORD: ${AUTH_PASSWORD:-} # Optional — generated automatically into the data volume if unset. SESSION_SECRET: ${SESSION_SECRET:-} SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-false} TRUST_PROXY: ${TRUST_PROXY:-} volumes: - ${WORKSHOP_DATA_DIR:-workshop-data}:/data - ${BACKUP_DIR:-./backups}:/backups ports: # Container side has to track PORT above — the app listens on exactly # one port and publishing a different one just yields a dead mapping. - "${HOST_PORT:-8080}:${APP_PORT:-3000}" # Off by default (mounts the Docker socket, which is root-equivalent on the # host) — enable with: docker compose --profile backup up -d backup: profiles: ["backup"] image: offen/docker-volume-backup:v2 restart: unless-stopped environment: BACKUP_CRON: "0 3 * * *" BACKUP_FILENAME: "workshop-backup-%Y-%m-%d_%H-%M-%S.tar.gz" BACKUP_RETENTION_DAYS: "${BACKUP_RETENTION_DAYS:-14}" BACKUP_STOP_DURING_BACKUP_LABEL: "workshop" BACKUP_PRUNING_LEEWAY: "5m" volumes: - ${WORKSHOP_DATA_DIR:-workshop-data}:/backup/workshop-data:ro - ${BACKUP_DIR:-./backups}:/archive - /var/run/docker.sock:/var/run/docker.sock:ro volumes: workshop-data: name: workshop-data