Rewrite SAAC_DEPLOYMENT.md to lead with the two-domain model: - Production (yourapp.<server>.domain.com) — updates on saac deploy - Hot-reload (yourapp-hot.<server>.domain.com) — auto-rebuilds on git push Added: recommended dev workflow (push → check hot → deploy to prod), nodemon.json explanation, development cycle diagram, customization guide. Updated Dockerfile and docker-compose.yml headers to explain which container uses which file and reference nodemon.json.
62 lines
2.1 KiB
Docker
62 lines
2.1 KiB
Docker
# Multi-stage Dockerfile for React + Express application (PRODUCTION container)
|
|
# See SAAC_DEPLOYMENT.md for deployment rules and common mistakes.
|
|
#
|
|
# This Dockerfile is ONLY used by the production container (yourapp.<server>.domain.com).
|
|
# The hot-reload container (yourapp-hot.<server>.domain.com) does NOT use this file —
|
|
# it mounts your source code directly and uses nodemon.json to watch for changes.
|
|
#
|
|
# 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 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
|
|
|
|
# --- Stage 2: Production server ---
|
|
FROM node:20-alpine
|
|
|
|
ARG SOURCE_COMMIT=unknown
|
|
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 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 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
|
|
|
|
CMD ["node", "server.js"]
|