# Build stage
FROM node:18-alpine AS builder
# Install pnpm
RUN npm install -g pnpm
WORKDIR /app
# Copy package files
COPY package.json pnpm-lock.yaml ./
# Install dependencies
RUN pnpm install
# Copy source files
COPY . .
# Build TypeScript
RUN pnpm build
# Production stage
FROM node:18-alpine AS production
# Install pnpm
RUN npm install -g pnpm
# Create a non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
# Copy package files
COPY package.json pnpm-lock.yaml ./
# Install production dependencies only
RUN pnpm install --prod
# Copy built files from builder stage
COPY --from=builder /app/dist ./dist
# Set ownership to non-root user
RUN chown -R appuser:appgroup /app
# Switch to non-root user
USER appuser
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "const http = require('http'); const options = { hostname: 'localhost', port: 3000, path: '/health', timeout: 2000 }; const req = http.get(options, (res) => { process.exit(res.statusCode === 200 ? 0 : 1); }); req.on('error', () => { process.exit(1); }); req.end();"
# Expose port
EXPOSE 5100
# Run the server
ENTRYPOINT ["node", "dist/index.js"]