screentinker/Dockerfile
ScreenTinker 4771f62623 ci: release pipeline (tarball, tizen wgt, multi-arch docker) + Docker packaging
- .github/workflows/release.yml: on a v* tag - verify the tag matches VERSION
  (fail-fast guard), run tests, build a source tarball + the unsigned Tizen .wgt
  and publish a GitHub Release with generated notes, and build+push a multi-arch
  (amd64 + arm64) image to ghcr.io/screentinker/screentinker:<version> + :latest.
  The Release (artifacts) and the docker push are independent jobs, so an
  arm64/QEMU docker failure does not block the GitHub Release and is re-runnable.
  Nothing deploys to prod. APK-build-in-CI left as a TODO (keystore secret).
- Dockerfile + .dockerignore: multi-stage node:20-slim image with server +
  frontend + VERSION + scripts; DATA_DIR=/data volume for db/uploads/jwt-secret.
  Verified to build, boot, serve the dashboard + web player, and persist state.
- docker-compose.example.yml: /data volume, SELF_HOSTED, a node-fetch healthcheck
  against /api/status, and an admin-lockout recovery note (reset-admin.js).
- server.js: resolve the OTA APK from DATA_DIR first (a container can mount one
  at /data/ScreenTinker.apk), fall back to the legacy in-repo path, 404 gracefully.
- ci.yml: bump checkout/setup-node to v6 (clears the Node-20 action deprecation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 13:44:51 -05:00

38 lines
1.5 KiB
Docker

# ScreenTinker server image: serves the dashboard, the web player, and the
# device API. All mutable state (db, uploads, jwt secret) lives under /data so it
# survives container restarts - mount a volume there. A built ScreenTinker.apk
# can be mounted at /data/ScreenTinker.apk to enable OTA APK downloads.
#
# No TLS in the image: it listens on plain HTTP :3001. Front it with a
# TLS-terminating reverse proxy / Cloudflare in production.
# --- builder: install production deps (native: better-sqlite3, sharp) ---
FROM node:20-slim AS builder
WORKDIR /app/server
# build toolchain in case a native prebuild is missing for the target arch
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 build-essential \
&& rm -rf /var/lib/apt/lists/*
COPY server/package.json server/package-lock.json ./
RUN npm ci --omit=dev
# --- runtime ---
FROM node:20-slim
ENV NODE_ENV=production
# Relocate all state onto the volume (config.js reads DATA_DIR; unset would use
# the in-repo paths, which we do not want in a container).
ENV DATA_DIR=/data
WORKDIR /app/server
# App source (node_modules/test/db/uploads/certs are excluded via .dockerignore),
# then the built deps, the frontend the server serves, and the VERSION file it
# reads as ../VERSION.
COPY server/ /app/server/
COPY --from=builder /app/server/node_modules /app/server/node_modules
COPY frontend/ /app/frontend/
COPY VERSION /app/VERSION
# database.js requires scripts/migrate-multitenancy at boot
COPY scripts/ /app/scripts/
VOLUME ["/data"]
EXPOSE 3001
CMD ["node", "server.js"]