FROM node:24.22.1-bookworm-slim AS build WORKDIR /app COPY package.json package-lock.json ./ COPY appview/tools/patch-jetstream.mjs ./appview/tools/patch-jetstream.mjs RUN npm ci --ignore-scripts \ && node appview/tools/patch-jetstream.mjs COPY . ./ ARG SITE_URL=http://127.0.0.1:3000/ ENV SITE_URL=${SITE_URL} RUN npm run build FROM node:24.22.1-bookworm-slim AS runtime ARG SITE_URL=http://127.0.0.1:3000/ ENV NODE_ENV=production HOST=0.0.0.0 PORT=3000 DATABASE_PATH=/data/appview.sqlite SITE_URL=${SITE_URL} WORKDIR /app COPY package.json package-lock.json ./ COPY appview/tools/patch-jetstream.mjs ./appview/tools/patch-jetstream.mjs RUN npm ci --omit=dev --ignore-scripts \ && node appview/tools/patch-jetstream.mjs \ && npm cache clean --force COPY --from=build --chown=node:node /app/build ./build COPY --from=build --chown=node:node /app/scripts/server.ts ./scripts/server.ts COPY --from=build --chown=node:node /app/appview/src ./appview/src COPY --from=build --chown=node:node /app/appview/migrations ./appview/migrations COPY --from=build --chown=node:node /app/src/core ./src/core COPY --from=build --chown=node:node /app/src/records ./src/records RUN mkdir /data && chown node:node /data USER node EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD node -e "const base = new URL(process.env.SITE_URL).pathname.replace(/\/+$/, ''); const path = process.env.HEALTHCHECK_PATH ?? base + '/healthz'; if (!path.startsWith('/') || path.startsWith('//')) process.exit(1); fetch(new URL(path, 'http://127.0.0.1:' + process.env.PORT)).then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))" CMD ["node", "--env-file-if-exists=.env.local", "scripts/server.ts"]