-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathDockerfile
More file actions
140 lines (112 loc) · 5.55 KB
/
Dockerfile
File metadata and controls
140 lines (112 loc) · 5.55 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
# syntax=docker/dockerfile:1
# =============================================================================
# LynxPrompt Dockerfile
# Multi-stage build for production (optimized with BuildKit)
# =============================================================================
# Build with: docker build --platform linux/amd64 -t <tag> .
# Requires: DOCKER_BUILDKIT=1 (default in modern Docker)
# =============================================================================
# -----------------------------------------------------------------------------
# Base stage - shared dependencies
# -----------------------------------------------------------------------------
FROM node:22-alpine AS base
# Install dependencies for Prisma and other native modules
RUN apk add --no-cache libc6-compat openssl
WORKDIR /app
# -----------------------------------------------------------------------------
# Dependencies stage - install dependencies with npm ci (faster, deterministic)
# -----------------------------------------------------------------------------
FROM base AS deps
# Copy package files
COPY package.json package-lock.json* ./
# npm install (not ci) tolerates lockfiles across npm versions (local npm 11 vs Docker npm 10)
# Cache keyed by TARGETPLATFORM to avoid ETXTBSY on QEMU cross-compilation
ARG TARGETPLATFORM
RUN --mount=type=cache,target=/root/.npm,id=npm-${TARGETPLATFORM} \
npm install
# -----------------------------------------------------------------------------
# Builder stage - build the application
# -----------------------------------------------------------------------------
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Generate all 4 Prisma clients in parallel (Prisma 7 with driver adapters)
RUN npx prisma generate --config=prisma/prisma.config-app.ts & \
npx prisma generate --config=prisma/prisma.config-users.ts & \
npx prisma generate --config=prisma/prisma.config-blog.ts & \
npx prisma generate --config=prisma/prisma.config-support.ts & \
wait
# Build the application with Next.js build cache
# NEXT_PUBLIC_* vars must be available at build time for Next.js to inline them
ARG NEXT_PUBLIC_UMAMI_WEBSITE_ID
ARG NEXT_PUBLIC_TURNSTILE_SITE_KEY
ARG UMAMI_SCRIPT_URL
ARG APP_URL
ENV NEXT_PUBLIC_UMAMI_WEBSITE_ID=${NEXT_PUBLIC_UMAMI_WEBSITE_ID}
ENV NEXT_PUBLIC_TURNSTILE_SITE_KEY=${NEXT_PUBLIC_TURNSTILE_SITE_KEY}
ENV UMAMI_SCRIPT_URL=${UMAMI_SCRIPT_URL}
ENV APP_URL=${APP_URL}
ENV NEXT_TELEMETRY_DISABLED=1
ENV TSC_COMPILE_ON_ERROR=true
# Disable Turbopack for production builds (fixes font resolution issues in Next.js 16)
ENV TURBOPACK=0
RUN --mount=type=cache,target=/app/.next/cache \
npm run build
# -----------------------------------------------------------------------------
# Prisma CLI stage - resolve full dep tree for migrations
# -----------------------------------------------------------------------------
FROM base AS prisma-deps
WORKDIR /prisma-deps
COPY --from=builder /app/package.json ./
ARG TARGETPLATFORM
RUN --mount=type=cache,target=/root/.npm,id=npm-prisma-${TARGETPLATFORM} \
npm install --no-save prisma tsx esbuild get-tsconfig resolve-pkg-maps
# -----------------------------------------------------------------------------
# Production stage - minimal runtime image
# -----------------------------------------------------------------------------
FROM base AS production
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Create non-root user for security
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Copy necessary files from builder
COPY --from=builder /app/public ./public
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/package.json ./package.json
# Copy Prisma CLI with full dependency tree (from dedicated stage)
COPY --from=prisma-deps /prisma-deps/node_modules ./node_modules
# Copy Prisma generated clients (Prisma 7 - generated to src/generated/)
COPY --from=builder /app/src/generated ./src/generated
# Copy pg driver for Prisma adapter runtime
COPY --from=builder /app/node_modules/pg ./node_modules/pg
COPY --from=builder /app/node_modules/pg-cloudflare ./node_modules/pg-cloudflare
COPY --from=builder /app/node_modules/pg-connection-string ./node_modules/pg-connection-string
COPY --from=builder /app/node_modules/pg-int8 ./node_modules/pg-int8
COPY --from=builder /app/node_modules/pg-pool ./node_modules/pg-pool
COPY --from=builder /app/node_modules/pg-protocol ./node_modules/pg-protocol
COPY --from=builder /app/node_modules/pg-types ./node_modules/pg-types
COPY --from=builder /app/node_modules/pgpass ./node_modules/pgpass
COPY --from=builder /app/node_modules/postgres-array ./node_modules/postgres-array
COPY --from=builder /app/node_modules/postgres-bytea ./node_modules/postgres-bytea
COPY --from=builder /app/node_modules/postgres-date ./node_modules/postgres-date
COPY --from=builder /app/node_modules/postgres-interval ./node_modules/postgres-interval
COPY --from=builder /app/node_modules/split2 ./node_modules/split2
# Set correct permissions for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
# Copy standalone build
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Copy entrypoint script and fix line endings (Windows CRLF -> Unix LF)
COPY --chown=nextjs:nodejs entrypoint.sh ./
RUN sed -i 's/\r$//' entrypoint.sh && chmod +x entrypoint.sh
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# Override base image entrypoint and use our script
ENTRYPOINT []
CMD ["/bin/sh", "./entrypoint.sh"]