Harden template for production: add comments, fix bugs, add lock file
- Add inline comments to docker-compose.yml explaining the 5 key rules (expose vs ports, DB host, DB name persistence, no Traefik labels) - Add comments to Dockerfile explaining multi-stage build, layer caching, and why .dockerignore excludes client/dist - Add comments to .dockerignore explaining each exclusion - Fix dev script: use nodemon (auto-restart) instead of node for server.js - Add postinstall script to auto-install client deps (cd client && npm install) - Fix SPA fallback: bare return → next() to prevent hanging requests - Add root package-lock.json for deterministic server dependency installs - Remove committed tsconfig.tsbuildinfo build artifact, add *.tsbuildinfo to .gitignore - Update README: simpler install (npm install handles everything), reference SAAC_DEPLOYMENT.md, use npx instead of pnpm dlx for shadcn components
This commit is contained in:
25
Dockerfile
25
Dockerfile
@@ -1,15 +1,27 @@
|
||||
# Multi-stage Dockerfile for React + Express application
|
||||
# See SAAC_DEPLOYMENT.md for deployment rules and common mistakes.
|
||||
#
|
||||
# Stage 1 (builder): Installs client deps and builds the React app with Vite.
|
||||
# Stage 2 (production): Installs server deps only, copies built React output.
|
||||
#
|
||||
# The .dockerignore excludes client/dist from the build context — this is
|
||||
# intentional. The builder stage creates a fresh dist/ inside the container,
|
||||
# and COPY --from=builder copies it between stages (bypasses .dockerignore).
|
||||
|
||||
# --- Stage 1: Build React frontend ---
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app/client
|
||||
|
||||
# Install client dependencies and build
|
||||
# Install client dependencies first (layer caching — only re-runs if package*.json change)
|
||||
COPY client/package*.json ./
|
||||
RUN npm install
|
||||
|
||||
# Copy client source and build
|
||||
COPY client/ ./
|
||||
RUN npm run build
|
||||
|
||||
# --- Production stage ---
|
||||
# --- Stage 2: Production server ---
|
||||
FROM node:20-alpine
|
||||
|
||||
ARG SOURCE_COMMIT=unknown
|
||||
@@ -17,23 +29,28 @@ ARG APP_VERSION=1.0.0
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# curl is required for the Docker healthcheck below
|
||||
RUN apk add --no-cache curl
|
||||
|
||||
# Install server dependencies
|
||||
# Install server dependencies only (not devDependencies — they're not needed in production).
|
||||
# If your app needs devDependencies for a build step (e.g. TypeScript), install ALL deps
|
||||
# first, run the build, then prune: RUN npm install && npm run build && npm prune --production
|
||||
COPY package*.json ./
|
||||
RUN npm install --production
|
||||
|
||||
# Copy server code
|
||||
COPY server.js ./
|
||||
|
||||
# Copy built React app from builder
|
||||
# Copy built React app from the builder stage (not from host — .dockerignore doesn't apply)
|
||||
COPY --from=builder /app/client/dist ./client/dist
|
||||
|
||||
ENV GIT_COMMIT=${SOURCE_COMMIT} \
|
||||
APP_VERSION=${APP_VERSION}
|
||||
|
||||
# Use "expose" in docker-compose.yml, not "ports". This EXPOSE is just documentation.
|
||||
EXPOSE 3000
|
||||
|
||||
# Healthcheck — must match the healthcheck in docker-compose.yml
|
||||
HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=2 \
|
||||
CMD curl -f http://localhost:3000/health || exit 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user