mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-28 15:51:29 +08:00
feat: Dockerfile + docker-compose for Node.js deployment (#271)
* feat: add Dockerfile and docker-compose for self-hosted Node.js deployment Multi-stage build using node:20-slim. Builder runs pnpm build:pages and the server bundle; runtime image carries the bundled entry, native deps (better-sqlite3) and the static frontend. A symlink keeps entry-node.ts's relative `../../dist` static root resolving correctly when running from packages/server/dist. Compose mounts a named volume at /data so the SQLite database persists across restarts. Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f * fix: harden Dockerfile with proper layer caching, non-root user, and secret handling Split build into deps/builder/runtime stages so pnpm install is cached until lockfile changes. Run the Node process as a non-root `zpan` user. Replace hardcoded BETTER_AUTH_SECRET with a required env var that fails loudly when missing. Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f --------- Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
**/node_modules
|
||||
**/dist
|
||||
**/.turbo
|
||||
**/.cache
|
||||
**/coverage
|
||||
**/.wrangler
|
||||
.git
|
||||
.github
|
||||
.vscode
|
||||
.idea
|
||||
e2e
|
||||
playwright-report
|
||||
test-results
|
||||
*.log
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
.dockerignore
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
|
||||
# ── Stage 1: install deps (cached until lockfile changes) ──────
|
||||
FROM node:20-slim AS deps
|
||||
RUN corepack enable && corepack prepare pnpm@10.30.2 --activate
|
||||
WORKDIR /app
|
||||
|
||||
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
|
||||
COPY packages/server/package.json packages/server/
|
||||
COPY packages/web/package.json packages/web/
|
||||
COPY packages/shared/package.json packages/shared/
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# ── Stage 2: build ─────────────────────────────────────────────
|
||||
FROM deps AS builder
|
||||
|
||||
COPY packages/ packages/
|
||||
|
||||
RUN pnpm build:pages
|
||||
RUN pnpm --filter @zpan/server build
|
||||
|
||||
# Extract production-only deps into a flat directory.
|
||||
# pnpm deploy bundles workspace packages (e.g. @zpan/shared) into node_modules.
|
||||
RUN pnpm --filter @zpan/server deploy --prod /app/pruned
|
||||
|
||||
# ── Stage 3: runtime ───────────────────────────────────────────
|
||||
FROM node:20-slim
|
||||
|
||||
RUN addgroup --system zpan && adduser --system --ingroup zpan zpan
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Frontend assets (vite outputs to repo-root/dist, see packages/web/vite.config.ts).
|
||||
# Placed at /app/packages/dist so the server's `serveStatic({ root: '../../dist' })`
|
||||
# resolves correctly when cwd is /app/packages/server/dist.
|
||||
COPY --from=builder /app/dist ./packages/dist
|
||||
|
||||
# Bundled server entrypoint
|
||||
COPY --from=builder /app/packages/server/dist ./packages/server/dist
|
||||
|
||||
# Production node_modules (native deps like better-sqlite3 + workspace deps).
|
||||
# Node resolves /app/packages/server/node_modules from cwd /app/packages/server/dist.
|
||||
COPY --from=builder /app/pruned/node_modules ./packages/server/node_modules
|
||||
|
||||
RUN mkdir -p /data && chown zpan:zpan /data
|
||||
|
||||
USER zpan
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=8222
|
||||
EXPOSE 8222
|
||||
|
||||
WORKDIR /app/packages/server/dist
|
||||
CMD ["node", "entry-node.js"]
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
zpan:
|
||||
build: .
|
||||
image: zpan:latest
|
||||
ports:
|
||||
- "8222:8222"
|
||||
environment:
|
||||
- PORT=8222
|
||||
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:?Set BETTER_AUTH_SECRET in .env or shell}
|
||||
- BETTER_AUTH_URL=${BETTER_AUTH_URL:-http://localhost:8222}
|
||||
- DATABASE_URL=/data/zpan.db
|
||||
volumes:
|
||||
- zpan-data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
zpan-data:
|
||||
Reference in New Issue
Block a user