-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
109 lines (98 loc) · 5.08 KB
/
Copy pathDockerfile
File metadata and controls
109 lines (98 loc) · 5.08 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
# StackAlchemist Multi-Component Dockerfile
# This file uses multi-stage builds and targets to build the Web, Engine, and Worker.
# ==========================================
# STAGE 1: NEXT.JS FRONTEND (WEB)
# ==========================================
FROM node:26-alpine AS web-builder
RUN apk add --no-cache git
WORKDIR /app
# Accept public env vars at build time so Next.js bakes them into the bundle.
# NEXT_PUBLIC_* vars are read at module scope (e.g. layout.tsx `isTestSite`)
# which means they must be present during `next build`, not just at runtime.
# Missing IS_TEST_SITE here is what historically broke the test-mirror noindex.
ARG NEXT_PUBLIC_APP_URL=https://test.stackalchemist.app
ARG NEXT_PUBLIC_IS_TEST_SITE=false
ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL
ENV NEXT_PUBLIC_IS_TEST_SITE=$NEXT_PUBLIC_IS_TEST_SITE
ARG NEXT_PUBLIC_SUPABASE_URL
ARG NEXT_PUBLIC_SUPABASE_ANON_KEY
ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
ARG NEXT_PUBLIC_PLAUSIBLE_DOMAIN
ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
ENV NEXT_PUBLIC_PLAUSIBLE_DOMAIN=$NEXT_PUBLIC_PLAUSIBLE_DOMAIN
# Copy manifests first so the install layer is cached independently of source.
COPY src/StackAlchemist.Web/package.json src/StackAlchemist.Web/package-lock.json ./
# Install all dependencies. --ignore-scripts skips postinstall (setup-env-safe.mjs)
# which requires the full scripts/ dir that isn't copied until the next step.
RUN npm install --include=dev --ignore-scripts
COPY src/StackAlchemist.Web/ .
# Docs, blog, compare, and solutions pages resolve their markdown via
# process.cwd()/../../<folder> at build time. CWD is /app, so these trees must
# live at /docs and /content for generateStaticParams + generateMetadata to read.
COPY docs/ /docs/
COPY content/ /content/
# Build the Next.js app and clean build cache.
# We invoke next build directly because the npm script wrapper
# (scripts/build-wrapper.mjs) is only needed on Windows+pnpm.
# --webpack opts out of Turbopack (Next 16 default); the custom webpack hook
# in next.config.ts (resolve.symlinks=false) only runs under webpack and is
# load-bearing for static prerendering on Windows local dev — keep webpack
# everywhere so Linux CI and Windows local stay in sync.
RUN npx next build --webpack \
&& rm -rf /root/.npm /tmp/*
FROM node:26-alpine AS web
# Install wget for production health checks
RUN apk add --no-cache wget
WORKDIR /app
ENV NODE_ENV=production
ENV HOSTNAME=0.0.0.0
ENV PORT=3000
COPY --from=web-builder /app/.next/standalone ./
COPY --from=web-builder /app/.next/static ./.next/static
COPY --from=web-builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
# ==========================================
# STAGE 2: .NET ENGINE (API)
# ==========================================
FROM mcr.microsoft.com/dotnet/sdk:10.0-resolute AS engine-builder
WORKDIR /src
COPY src/StackAlchemist.Engine/*.csproj ./StackAlchemist.Engine/
RUN dotnet restore ./StackAlchemist.Engine/StackAlchemist.Engine.csproj
COPY src/StackAlchemist.Engine/ ./StackAlchemist.Engine/
RUN dotnet publish ./StackAlchemist.Engine/StackAlchemist.Engine.csproj -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:10.0-resolute AS engine
RUN apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/*
ENV ASPNETCORE_URLS=http://+:80
WORKDIR /app
COPY --from=engine-builder /app/publish .
# Handlebars template sets are loaded from disk at runtime and are NOT part of the
# published DLL output. Copy them next to the entrypoint — TemplatesRootResolver probes
# <BaseDirectory>/StackAlchemist.Templates first, which is /app here. Without this the
# engine reports "Template set ... not found. Available: none" and all codegen fails.
COPY src/StackAlchemist.Templates/ ./StackAlchemist.Templates/
EXPOSE 80
EXPOSE 443
ENTRYPOINT ["dotnet", "StackAlchemist.Engine.dll"]
# ==========================================
# STAGE 3: .NET WORKER (COMPILE GUARANTEE)
# ==========================================
FROM mcr.microsoft.com/dotnet/sdk:10.0-resolute AS worker-builder
WORKDIR /src
# Worker references Engine — copy both .csproj files before restore so the
# dependency graph can be resolved, then copy full source for both projects.
COPY src/StackAlchemist.Engine/*.csproj ./StackAlchemist.Engine/
COPY src/StackAlchemist.Worker/*.csproj ./StackAlchemist.Worker/
RUN dotnet restore ./StackAlchemist.Worker/StackAlchemist.Worker.csproj
COPY src/StackAlchemist.Engine/ ./StackAlchemist.Engine/
COPY src/StackAlchemist.Worker/ ./StackAlchemist.Worker/
RUN dotnet publish ./StackAlchemist.Worker/StackAlchemist.Worker.csproj -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/sdk:10.0-resolute AS worker
# Note: Worker needs SDK to run 'dotnet build' on generated repos
WORKDIR /app
COPY --from=worker-builder /app/publish .
# Install Node.js in the worker container so it can run 'npm build' on generated repos
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs
ENTRYPOINT ["dotnet", "StackAlchemist.Worker.dll"]