feat(project): add Docker Compose with flexible storage and DB modes
Bundle the app + Postgres into a compose stack on top of the existing image.
- app: builds the image, publishes ${APP_PORT:-42776}, reads .env, pins
STATIC_DIR so SPA serving can't be disabled by an empty value
- db: postgres:14-alpine under the "with-db" profile; toggle it off via
COMPOSE_PROFILES to point the app at a Postgres on the host instead
(host.docker.internal), with depends_on required:false so it stays optional
Storage and the DB data dir each default to a named volume but can be bind
mounted to a host folder via FILES_DIR / THUMBS_DIR / IMPORT_DIR / DB_DIR.
Add PUID/PGID (via user:) so bind-mounted folders are writable by the
non-root container.
Run the container as a dedicated non-root user "tanabata" with uid/gid 42776,
reusing the project's signature number (also the default port). Document every
variable in .env.example.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# =============================================================================
|
||||
# Tanabata File Manager — Docker Compose
|
||||
#
|
||||
# Quick start:
|
||||
# cp .env.example .env # then edit the secrets
|
||||
# docker compose up -d --build
|
||||
#
|
||||
# Database — two supported modes, selected in .env:
|
||||
#
|
||||
# 1. Bundled Postgres container (default).
|
||||
# COMPOSE_PROFILES=with-db
|
||||
# DATABASE_URL=postgres://tanabata:password@db:5432/tanabata?sslmode=disable
|
||||
#
|
||||
# 2. Postgres already running on the host.
|
||||
# COMPOSE_PROFILES= # empty → the db container is not started
|
||||
# DATABASE_URL=postgres://tanabata:password@host.docker.internal:5432/tanabata?sslmode=disable
|
||||
#
|
||||
# Requires Docker Compose v2.20+ (for depends_on.required).
|
||||
# =============================================================================
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
|
||||
# All application config (secrets, DATABASE_URL, tunables) comes from .env.
|
||||
env_file: .env
|
||||
|
||||
# Pin STATIC_DIR to the path baked into the image. .env intentionally leaves
|
||||
# it unset; pinning here guarantees in-container SPA serving can't be
|
||||
# disabled by an empty value leaking in through env_file.
|
||||
environment:
|
||||
STATIC_DIR: /app/static
|
||||
|
||||
# The container always listens on 42776 (Dockerfile default); APP_PORT only
|
||||
# changes the host-published port.
|
||||
ports:
|
||||
- "${APP_PORT:-42776}:42776"
|
||||
|
||||
# Wait for the bundled DB when the with-db profile is active. When using a
|
||||
# host Postgres the db service is disabled, and required:false keeps this
|
||||
# dependency from erroring or auto-starting it.
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
required: false
|
||||
|
||||
# Lets DATABASE_URL reach a Postgres on the host via host.docker.internal
|
||||
# (needed on Linux; harmless elsewhere).
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
# Run as this uid:gid. Relevant when the mounts below are bind-mounted to
|
||||
# host folders: set PUID/PGID (in .env) to the owner of those folders so the
|
||||
# container can write to them. Defaults to the image's tanabata user
|
||||
# (42776), which owns the named volumes.
|
||||
user: "${PUID:-42776}:${PGID:-42776}"
|
||||
|
||||
# Storage for originals, the thumbnail cache, and the import drop folder.
|
||||
# Each source defaults to a named volume but can be pointed at a specific
|
||||
# host folder via FILES_DIR / THUMBS_DIR / IMPORT_DIR in .env (a path turns
|
||||
# the mount into a host bind mount; a bare name stays a named volume).
|
||||
volumes:
|
||||
- "${FILES_DIR:-app_files}:/data/files"
|
||||
- "${THUMBS_DIR:-app_thumbs}:/data/thumbs"
|
||||
- "${IMPORT_DIR:-app_import}:/data/import"
|
||||
|
||||
db:
|
||||
image: postgres:14-alpine
|
||||
restart: unless-stopped
|
||||
|
||||
# Only started when COMPOSE_PROFILES includes "with-db". Disable it to point
|
||||
# the app at a Postgres running on the host instead.
|
||||
profiles: ["with-db"]
|
||||
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-tanabata}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-tanabata}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password}
|
||||
|
||||
# Defaults to a named volume; set DB_DIR in .env to a host folder to bind
|
||||
# mount it instead. Postgres fixes the folder's ownership itself, so DB_DIR
|
||||
# needs no PUID/PGID.
|
||||
volumes:
|
||||
- "${DB_DIR:-db_data}:/var/lib/postgresql/data"
|
||||
|
||||
# Uncomment to reach the DB from the host (e.g. with psql) for debugging.
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-tanabata} -d ${POSTGRES_DB:-tanabata}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
app_files:
|
||||
app_thumbs:
|
||||
app_import:
|
||||
db_data:
|
||||
Reference in New Issue
Block a user