# ═══════════════════════════════════════════════ # Harat's Booking — Production Dockerfile # ═══════════════════════════════════════════════ # ── Stage 1: Install production dependencies ── FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ COPY server/package.json ./server/package.json COPY packages/shared/package.json ./packages/shared/package.json COPY packages/shared/ ./packages/shared/ RUN npm install --omit=dev --workspace=server --workspace=packages/shared COPY server/prisma ./server/prisma RUN cd server && npx -y prisma generate # ── Stage 2: Final Image ── FROM node:20-alpine WORKDIR /app # Create user + dirs FIRST RUN addgroup -S harats && adduser -S harats -G harats \ && mkdir -p /data/logs \ && chown -R harats:harats /data /app # Runtime deps + pm2 (install as root, then fix ownership) RUN apk add --no-cache curl \ && npm install -g pm2@latest \ && pm2 install pm2-logrotate \ && pm2 set pm2-logrotate:max_size 10M \ && pm2 set pm2-logrotate:retain 7 \ && pm2 set pm2-logrotate:compress true \ && pm2 kill # Copy node_modules COPY --chown=harats:harats --from=deps /app/node_modules ./node_modules # Copy server compiled source (tsc outputs to dist/src/) COPY --chown=harats:harats server/dist ./dist COPY --chown=harats:harats server/prisma ./prisma # Copy pre-built client dist COPY --chown=harats:harats client/dist ./public # Copy ecosystem config + version COPY --chown=harats:harats ecosystem.config.cjs ./ecosystem.config.cjs COPY --chown=harats:harats version.json ./version.json # Version info ARG BUILD_VERSION=0.0.0 ARG BUILD_DATE=unknown RUN echo "{\"version\":\"${BUILD_VERSION}\",\"build\":\"$(echo $BUILD_DATE | cut -c1-16)\",\"buildDate\":\"${BUILD_DATE}\"}" > version.json USER harats EXPOSE 3001 HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ CMD curl -sf http://localhost:3001/api/health || exit 1 CMD ["pm2-runtime", "ecosystem.config.cjs"]