The first phase-11 file op (inline rename) returns EROFS today because docker-compose mounts ~/Pictures read-only by default. Lightroom-style file operations (rename, move, discard-pile empty) all need to mutate the filesystem, so the right default is :rw. Flips both the backend and worker mounts to :rw with an inline comment explaining the trade-off, and adds a "Photo directory mounts and permissions" section to the README that: - States the default is now :rw - Explains exactly which endpoints fail under :ro (rename, empty discard pile, future move/copy) - Notes the implication: Mulita has full write access to whatever host directory ends up at /host/Pictures, same trust model as Lightroom's catalog folder Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
98 lines
2.5 KiB
YAML
98 lines
2.5 KiB
YAML
version: '3.8'
|
|
|
|
services:
|
|
frontend:
|
|
build:
|
|
context: ./frontend
|
|
dockerfile: Dockerfile
|
|
container_name: mulita-frontend
|
|
ports:
|
|
- "3000:80"
|
|
depends_on:
|
|
- backend
|
|
networks:
|
|
- mulita-network
|
|
restart: unless-stopped
|
|
|
|
backend:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
container_name: mulita-backend
|
|
ports:
|
|
- "8001:8000"
|
|
volumes:
|
|
- ./mulita.yml:/app/config/mulita.yml:ro
|
|
- ${PHOTO_DIRS:-./photos}:/photos:rw
|
|
# NOTE: read-write — file operations (rename, move, discard,
|
|
# empty discard pile) need to mutate the filesystem. Flip to :ro
|
|
# if you want a strict read-only library; the rename / move /
|
|
# delete endpoints will then return EROFS.
|
|
- ~/Pictures:/host/Pictures:rw
|
|
- thumbs_data:/data/thumbs
|
|
- proxies_data:/data/proxies
|
|
- db_data:/data/db
|
|
- trash_data:/data/trash
|
|
environment:
|
|
- DATABASE_URL=sqlite+aiosqlite:////data/db/mulita.db
|
|
- REDIS_URL=redis://redis:6379
|
|
- CELERY_BROKER_URL=redis://redis:6379
|
|
- CELERY_RESULT_BACKEND=redis://redis:6379
|
|
- PHOTO_DIRS=${PHOTO_DIRS:-/photos}
|
|
depends_on:
|
|
- redis
|
|
networks:
|
|
- mulita-network
|
|
restart: unless-stopped
|
|
|
|
worker:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
container_name: mulita-worker
|
|
command: celery -A app.tasks.celery worker --loglevel=info --concurrency=4
|
|
volumes:
|
|
- ./mulita.yml:/app/config/mulita.yml:ro
|
|
- ${PHOTO_DIRS:-./photos}:/photos:rw
|
|
# See backend service for the rationale on :rw.
|
|
- ~/Pictures:/host/Pictures:rw
|
|
- thumbs_data:/data/thumbs
|
|
- proxies_data:/data/proxies
|
|
- db_data:/data/db
|
|
- trash_data:/data/trash
|
|
environment:
|
|
- DATABASE_URL=sqlite+aiosqlite:////data/db/mulita.db
|
|
- REDIS_URL=redis://redis:6379
|
|
- CELERY_BROKER_URL=redis://redis:6379
|
|
- CELERY_RESULT_BACKEND=redis://redis:6379
|
|
- PHOTO_DIRS=${PHOTO_DIRS:-/photos}
|
|
- CELERYD_CONCURRENCY=4
|
|
depends_on:
|
|
- redis
|
|
- backend
|
|
networks:
|
|
- mulita-network
|
|
restart: unless-stopped
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: mulita-redis
|
|
ports:
|
|
- "6379:6379"
|
|
volumes:
|
|
- redis_data:/data
|
|
networks:
|
|
- mulita-network
|
|
restart: unless-stopped
|
|
command: redis-server --appendonly yes
|
|
|
|
networks:
|
|
mulita-network:
|
|
driver: bridge
|
|
|
|
volumes:
|
|
thumbs_data:
|
|
proxies_data:
|
|
db_data:
|
|
trash_data:
|
|
redis_data: |