# ======================================== # Multi-stage Dockerfile for Backend Node.js # ======================================== # ======================================== # Stage 1: Base # ======================================== FROM node:20-alpine AS base # Install dumb-init for proper signal handling RUN apk add --no-cache dumb-init # Set working directory WORKDIR /app # Copy package files for dependency installation COPY package*.json ./ # ======================================== # Stage 2: Dependencies # ======================================== FROM base AS dependencies # Install ALL dependencies (including devDependencies for build) RUN npm install # ======================================== # Stage 3: Development # ======================================== FROM dependencies AS development # Set NODE_ENV ENV NODE_ENV=development # Copy application code COPY . . # Expose port EXPOSE 3000 # Use dumb-init to handle signals properly ENTRYPOINT ["dumb-init", "--"] # Start with nodemon for hot reload CMD ["npm", "start"] # ======================================== # Stage 4: Production Dependencies # ======================================== FROM base AS production-dependencies # Install only production dependencies RUN npm install --only=production && \ npm cache clean --force # ======================================== # Stage 5: Production Build # ======================================== FROM base AS production # Set NODE_ENV ENV NODE_ENV=production # Copy production dependencies COPY --from=production-dependencies /app/node_modules ./node_modules # Copy application code COPY . . # Create non-root user for security RUN addgroup -g 1001 -S nodejs && \ adduser -S nodejs -u 1001 && \ chown -R nodejs:nodejs /app # Switch to non-root user USER nodejs # Expose port EXPOSE 3000 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" # Use dumb-init to handle signals properly ENTRYPOINT ["dumb-init", "--"] # Start the application CMD ["node", "server.js"]