UNPKG

ethercalc

Version:

Multi-User Spreadsheet Server — TypeScript rewrite (Cloudflare fullstack)

110 lines (105 loc) 4.48 kB
# EtherCalc self-host compose file (§13 Q5). # # Default service — the standalone workerd Worker. No Redis: room state # lives in Durable Object SQLite files under the `./ethercalc-data` # bind-mounted at /data in the container. `docker compose up -d` is the # whole install story. # # Migration profile — activated with `--profile migrate`, adds two # short-lived services (`legacy-redis` + `migrator`) that ingest a # legacy Redis dump.rdb into the new Worker in one shot. Driven by # `bin/migrate-legacy.sh`; end users should not invoke the profile # directly. services: ethercalc: build: context: . dockerfile: Dockerfile image: ethercalc:selfhost container_name: ethercalc restart: unless-stopped ports: # Host 8000 matches the legacy port from the old compose file. - "8000:8000" volumes: # Persistent Durable Object state. Survives container restarts. # Created on first `up` if missing. - ./ethercalc-data:/data environment: # All variables are optional; sensible defaults live in the image. # Pass through from the host so `ETHERCALC_KEY=secret docker compose # up -d` Just Works without editing this file. ETHERCALC_PORT: "${ETHERCALC_PORT:-8000}" ETHERCALC_HOST: "${ETHERCALC_HOST:-0.0.0.0}" ETHERCALC_KEY: "${ETHERCALC_KEY:-}" ETHERCALC_DISABLE_ROOM_INDEX: "${ETHERCALC_DISABLE_ROOM_INDEX:-1}" ETHERCALC_CORS: "${ETHERCALC_CORS:-}" ETHERCALC_BASEPATH: "${ETHERCALC_BASEPATH:-}" ETHERCALC_EXPIRE: "${ETHERCALC_EXPIRE:-}" # Always forwarded; the migrate endpoint returns 404 when unset # so leaving it blank keeps the route invisible in normal runs. ETHERCALC_MIGRATE_TOKEN: "${ETHERCALC_MIGRATE_TOKEN:-}" # Health check lets the migrator service wait until /_health is # answering before firing the first seed PUT. healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8000/_health >/dev/null || exit 1"] interval: 2s timeout: 2s retries: 60 start_period: 5s # ────────────────────────── migration profile ────────────────────────── # Activated with `docker compose --profile migrate up`. Typical entry # point is `./bin/migrate-legacy.sh`, which wires the dump file, token, # and post-run backup in one go. legacy-redis: profiles: ["migrate"] image: redis:7-alpine container_name: ethercalc-legacy-redis # Redis's upstream entrypoint chowns /data/* at startup, which # fails against a read-only bind mount. Bind the user's dump to # an /input/ stage instead, copy it into the container-owned # /data at boot, then exec redis. Side effect: peak disk use # during migration is 2× the dump size (acceptable — migration # is transient, and the host copy is preserved untouched). entrypoint: ["/bin/sh", "-c"] command: - 'cp /input/dump.rdb /data/dump.rdb && exec redis-server --dir /data --dbfilename dump.rdb --save "" --appendonly no' volumes: # `ETHERCALC_LEGACY_DUMP` is set by `bin/migrate-legacy.sh` to # the absolute path of the user's dump.rdb. `:ro` guarantees the # source file is never modified even if something in the stack # misbehaves. - "${ETHERCALC_LEGACY_DUMP:-./legacy-dump.rdb}:/input/dump.rdb:ro" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 2s timeout: 2s retries: 60 start_period: 5s migrator: profiles: ["migrate"] image: ethercalc:selfhost container_name: ethercalc-migrator # Same image as the worker — bun + bin/ethercalc are already there. # One-shot: `ethercalc migrate`, then exit. `--abort-on-container- # exit` + `--exit-code-from migrator` on `docker compose up` makes # the wrapper script fail loudly if the migrator itself fails. depends_on: legacy-redis: condition: service_healthy ethercalc: condition: service_healthy environment: ETHERCALC_MIGRATE_TOKEN: "${ETHERCALC_MIGRATE_TOKEN:-}" entrypoint: ["/app/bin/ethercalc"] command: - "migrate" - "--source" - "redis://legacy-redis:6379" - "--target" - "http://ethercalc:8000" - "--token" - "${ETHERCALC_MIGRATE_TOKEN:-}" - "--concurrency" - "${ETHERCALC_MIGRATE_CONCURRENCY:-8}" restart: "no"