From bb15bfef28e4a7feafcab208ba63b6af3233e08a Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Sat, 27 Sep 2025 00:32:23 +0700 Subject: [PATCH] feat: add dockerfile --- Dockerfile | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..55d2923 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,76 @@ +# Development stage - for docker-compose development with hot reload +FROM node:20-alpine AS development +WORKDIR /app + +# Install pnpm globally +RUN npm install -g pnpm + +# Copy package files for dependency installation +COPY package*.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile + +# Copy source code +COPY . . + +# Expose port +EXPOSE 3000 + +# Use development command with hot reload +CMD ["pnpm", "dev"] + +# Builder stage - for production build +FROM node:20-alpine AS builder +WORKDIR /app + +# Install pnpm globally +RUN npm install -g pnpm + +# Copy package files +COPY package*.json pnpm-lock.yaml ./ + +# Install all dependencies (including dev dependencies for build) +RUN pnpm install --frozen-lockfile + +# Copy source code +COPY . . + +# Build TypeScript to JavaScript +RUN pnpm build + +# Production stage - optimized final image +FROM node:20-alpine AS production +WORKDIR /app + +# Create non-root user for security +RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001 + +# Install pnpm globally +RUN npm install -g pnpm + +# Copy package files +COPY --from=builder /app/package*.json ./ +COPY --from=builder /app/pnpm-lock.yaml ./ + +# Install only production dependencies +RUN pnpm install --prod --frozen-lockfile + +# Copy built application +COPY --from=builder /app/dist ./dist + +# Create required directories and set ownership +RUN mkdir -p logs && 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=60s --retries=3 \ + CMD node -e "require('http').request('http://localhost:3000/health', (res) => { \ + process.exit(res.statusCode === 200 ? 0 : 1) \ + }).on('error', () => process.exit(1)).end()" + +# Start the application +CMD ["node", "dist/server.js"] \ No newline at end of file