forked from Dushyant-rahangdale/OpsKnight
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
142 lines (111 loc) · 4.9 KB
/
Copy pathDockerfile
File metadata and controls
142 lines (111 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# syntax=docker/dockerfile:1
# Stage 1: Dependencies
FROM node:20-alpine AS deps
WORKDIR /app
# Make npm installs more resilient in CI/buildx (esp. arm64)
ENV NPM_CONFIG_FETCH_RETRIES=5 \
NPM_CONFIG_FETCH_RETRY_FACTOR=2 \
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT=20000 \
NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT=120000 \
NPM_CONFIG_NETWORK_TIMEOUT=600000 \
NPM_CONFIG_AUDIT=false \
NPM_CONFIG_FUND=false
# Install security updates and required packages
RUN apk update && apk upgrade && \
apk add --no-cache libc6-compat openssl openssl-dev && \
rm -rf /var/cache/apk/*
# Copy package files
COPY package*.json ./
# Add build arg to bust cache for migrations (ensures new migrations are always copied)
ARG BUILD_DATE=unknown
RUN echo "Build date: $BUILD_DATE"
COPY prisma ./prisma/
# Install production dependencies including optional dependencies
# Optional dependencies (twilio, @sendgrid/mail, resend, nodemailer, @aws-sdk/client-sns)
# are needed for notification features. npm ci --omit=dev installs optionalDependencies by default.
RUN npm ci --omit=dev --legacy-peer-deps --ignore-scripts --no-audit --no-fund && \
npm cache clean --force && \
rm -rf /tmp/*
# Stage 2: Builder
FROM node:20-alpine AS builder
WORKDIR /app
# Make npm installs more resilient in CI/buildx (esp. arm64)
ENV NPM_CONFIG_FETCH_RETRIES=5 \
NPM_CONFIG_FETCH_RETRY_FACTOR=2 \
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT=20000 \
NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT=120000 \
NPM_CONFIG_NETWORK_TIMEOUT=600000 \
NPM_CONFIG_AUDIT=false \
NPM_CONFIG_FUND=false
# Install security updates
RUN apk update && apk upgrade && \
apk add --no-cache libc6-compat openssl openssl-dev && \
rm -rf /var/cache/apk/*
# Copy package files
COPY package*.json ./
# Add build arg to bust cache for migrations
ARG BUILD_DATE=unknown
RUN echo "Build date: $BUILD_DATE"
COPY prisma ./prisma/
# Install all dependencies (including dev) - essential for build steps
RUN npm ci --legacy-peer-deps --ignore-scripts --no-audit --no-fund && \
npm cache clean --force
# Copy application source
COPY . .
# Generate Prisma Client
RUN npx prisma generate
# Set a dummy DATABASE_URL for build time only (Prisma requires it for validation)
# This will be overridden by the actual DATABASE_URL at runtime
# checkov:skip=CKV_SECRET_4: This is a dummy DATABASE_URL for build time only
ARG DATABASE_URL="postgresql://dummy:dummy@localhost:5432/dummy?schema=public"
ENV DATABASE_URL=$DATABASE_URL
# Build Next.js application with production optimizations
# Pages that need database access are marked as dynamic, so build works without DB
RUN npm run build
# Compile helper scripts for production (where ts-node is not available)
RUN npm run build:scripts
# Stage 3: Production Runner
FROM node:20-alpine AS runner
WORKDIR /app
# Install security updates and required runtime packages
RUN apk update && apk upgrade && \
apk add --no-cache curl openssl openssl-dev && \
rm -rf /var/cache/apk/* && \
rm -rf /tmp/*
# Set environment to production
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Create non-root user with specific UID/GID for consistency
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 --ingroup nodejs nextjs && \
mkdir -p /app && \
chown -R nextjs:nodejs /app
# Copy necessary files from builder
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma
COPY --from=builder --chown=nextjs:nodejs /app/package*.json ./
COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts
# Copy base node_modules first
COPY --from=deps --chown=nextjs:nodejs /app/node_modules ./node_modules
# Then copy Prisma-specific files (must be AFTER base node_modules to avoid being overwritten)
# This ensures Prisma CLI and client are available for migrations
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/prisma ./node_modules/prisma
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma
# Switch to non-root user
USER nextjs
# Expose port
EXPOSE 3000
# Set port environment variable
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# Copy entrypoint script
COPY --chown=nextjs:nodejs docker-entrypoint.sh ./
RUN chmod +x docker-entrypoint.sh
# Health check with improved error handling
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/api/health?mode=readiness', (r) => {let data='';r.on('data',(c)=>data+=c);r.on('end',()=>{const res=JSON.parse(data);process.exit(res.status==='healthy'?0:1)});}).on('error',()=>process.exit(1))"
# Run entrypoint which does: migrate → start app
ENTRYPOINT ["./docker-entrypoint.sh"]