Google-SSO PWA for bistro employee clock-in/out, admin employee management, and stats with CSV export. Express + SQLite backend, React + Zustand frontend in the light-mono-tui design language. Multi-stage Dockerfile, compose.yaml for image-based deploys, nginx reverse-proxy template, and an OKF documentation bundle in docs/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
43 lines
1.3 KiB
Docker
43 lines
1.3 KiB
Docker
# syntax=docker/dockerfile:1
|
|
|
|
# ---- frontend build: React/Vite PWA -> static dist/ ----
|
|
FROM node:22-slim AS frontend-build
|
|
WORKDIR /app/frontend
|
|
COPY frontend/package.json frontend/package-lock.json ./
|
|
RUN npm ci
|
|
COPY frontend/ .
|
|
# Vite inlines VITE_* env vars at build time, so the Google client id has to
|
|
# be supplied as a build arg: docker build --build-arg VITE_GOOGLE_CLIENT_ID=...
|
|
ARG VITE_GOOGLE_CLIENT_ID
|
|
ENV VITE_GOOGLE_CLIENT_ID=$VITE_GOOGLE_CLIENT_ID
|
|
RUN npm run build
|
|
|
|
# ---- backend build: TypeScript -> single esbuild bundle ----
|
|
FROM node:22-slim AS backend-build
|
|
WORKDIR /app/backend
|
|
COPY backend/package.json backend/package-lock.json ./
|
|
RUN npm ci
|
|
COPY backend/ .
|
|
RUN npm run build
|
|
|
|
# ---- runtime: only prod deps + the two build outputs ----
|
|
FROM node:22-slim AS runtime
|
|
ENV NODE_ENV=production
|
|
WORKDIR /app
|
|
|
|
# better-sqlite3 has a native binding, so it's installed for real here rather
|
|
# than copied from another stage — same base image as backend-build, so the
|
|
# compiled binary always matches what it runs on.
|
|
COPY backend/package.json backend/package-lock.json ./
|
|
RUN npm ci --omit=dev && npm cache clean --force
|
|
|
|
COPY --from=backend-build /app/backend/dist ./dist
|
|
COPY --from=frontend-build /app/frontend/dist ./dist/public
|
|
|
|
ENV PORT=4000
|
|
ENV DB_PATH=/app/data/eatme.db
|
|
EXPOSE 4000
|
|
VOLUME ["/app/data"]
|
|
|
|
CMD ["node", "dist/index.js"]
|