# ====================== # Stage 1: Dependencies # ====================== FROM node:20-alpine AS deps WORKDIR /app # Copy package files COPY package*.json ./ # Install dependencies (including devDependencies for build) # Use npm ci if package-lock.json exists, otherwise use npm install RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi # ====================== # Stage 2: Builder # ====================== FROM node:20-alpine AS builder WORKDIR /app # Copy dependencies from deps stage COPY --from=deps /app/node_modules ./node_modules # Copy application source COPY . . # Accept build arguments for Nuxt build-time configuration ARG SITE_URL=https://church.example.com ARG EMAIL_HOST=smtp.example.com ARG EMAIL_PORT=587 ARG EMAIL_USER=noreply@example.com ARG EMAIL_PASSWORD=your-email-password ARG EMAIL_FROM=New Life Christian Church # Set environment variables for build ENV SITE_URL=$SITE_URL ENV EMAIL_HOST=$EMAIL_HOST ENV EMAIL_PORT=$EMAIL_PORT ENV EMAIL_USER=$EMAIL_USER ENV EMAIL_PASSWORD=$EMAIL_PASSWORD ENV EMAIL_FROM=$EMAIL_FROM # Build the application RUN npm run build # Remove development dependencies after build RUN npm prune --production # ====================== # Stage 3: Runtime # ====================== FROM node:20-alpine AS runtime WORKDIR /app # Install dumb-init for proper signal handling RUN apk add --no-cache dumb-init # Create non-root user for security RUN addgroup -g 1001 -S nodejs && \ adduser -S nuxt -u 1001 # Copy only production dependencies and built output COPY --from=builder --chown=nuxt:nodejs /app/.output ./.output COPY --from=builder --chown=nuxt:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nuxt:nodejs /app/package.json ./package.json # Create data directory for SQLite database with proper permissions RUN mkdir -p /app/data && chown -R nuxt:nodejs /app/data # Switch to non-root user USER nuxt # Expose port EXPOSE 3000 # Set runtime environment variables ENV NODE_ENV=production ENV NUXT_HOST=0.0.0.0 ENV NUXT_PORT=3000 # Security: AUTH_SECRET and admin credentials are auto-generated on first launch # They are stored in the database and logged once to container logs # Use: docker logs | grep "ADMIN CREDENTIALS" to retrieve them # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" || exit 1 # Use dumb-init to properly handle signals ENTRYPOINT ["dumb-init", "--"] CMD ["node", ".output/server/index.mjs"]