11# Multi-stage Dockerfile to run ASP.NET Core + Next.js in a single container
22
3- # 1. Build .NET app
3+ # Build arguments
4+ ARG KAMAL_DEPLOY_HOST
5+ ARG SERVICESTACK_LICENSE
6+ ARG SERVICE_LABEL
7+
8+ # 1. Build .NET app + Node.js apps
49FROM mcr.microsoft.com/dotnet/sdk:10.0 AS dotnet-build
10+ ARG KAMAL_DEPLOY_HOST
11+ ENV KAMAL_DEPLOY_HOST=${KAMAL_DEPLOY_HOST}
12+
513WORKDIR /src
614
15+ # Install Node.js for building Tailwind CSS and Next.js
16+ RUN apt-get update \
17+ && apt-get install -y curl ca-certificates gnupg \
18+ && curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \
19+ && apt-get install -y nodejs \
20+ && apt-get clean \
21+ && rm -rf /var/lib/apt/lists/*
22+
723# Copy solution and projects
824COPY TechStacks.sln ./
925COPY TechStacks ./TechStacks
1026COPY TechStacks.ServiceInterface ./TechStacks.ServiceInterface
1127COPY TechStacks.ServiceModel ./TechStacks.ServiceModel
1228
13- # Restore and publish only the API project (avoid solution projects not copied into the image)
14- RUN dotnet restore TechStacks/ TechStacks.csproj
15- # Disable .NET's built-in containerization (PublishProfile=DefaultContainer) inside Docker
16- RUN dotnet publish TechStacks/TechStacks.csproj -c Release --no-restore -p:PublishProfile=
29+ # Build Tailwind CSS for .NET project
30+ WORKDIR /src/ TechStacks
31+ RUN npm install
32+ RUN npm run ui:build
1733
18- # 2. Build Next.js app
19- FROM node:20-alpine AS next-build
20- ARG KAMAL_DEPLOY_HOST
21- ENV KAMAL_DEPLOY_HOST=${KAMAL_DEPLOY_HOST}
22-
23- WORKDIR /app/client
34+ # Build Next.js app
2435
36+ WORKDIR /src/TechStacks.Client
2537COPY TechStacks.Client/package*.json ./
2638RUN npm ci
2739COPY TechStacks.Client/ ./
28-
29- # Build Next.js in server mode
3040RUN npm run build:prod
3141
32- # 3. Runtime image with .NET + Node
42+ # Restore and publish .NET app
43+ WORKDIR /src
44+ RUN dotnet restore TechStacks/TechStacks.csproj
45+ # Disable .NET's built-in containerization (PublishProfile=DefaultContainer) inside Docker
46+ RUN dotnet publish TechStacks/TechStacks.csproj -c Release --no-restore -p:PublishProfile=
47+
48+ # 2. Runtime image with .NET + Node
3349FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
50+ ARG SERVICESTACK_LICENSE
51+ ARG SERVICE_LABEL
52+ ARG KAMAL_DEPLOY_HOST
53+
3454WORKDIR /app
3555
36- # Label required by Kamal, must match config/deploy.yml service (techstacks-io)
37- LABEL service="techstacks-io"
38-
39- ARG SERVICESTACK_LICENSE
56+ # Label required by Kamal, must match config/deploy.yml service
57+ LABEL service="${SERVICE_LABEL}"
4058
4159# Install Node.js >= 20.9 (Node 24.x LTS) and bash for the entrypoint script
4260RUN apt-get update \
@@ -49,14 +67,15 @@ RUN apt-get update \
4967# Copy published .NET app
5068COPY --from=dotnet-build /src/TechStacks/bin/Release/net10.0/publish ./api
5169
52- # Copy built Next.js app (including .next , node_modules, public, etc.)
53- COPY --from=next -build /app/client ./client
70+ # Copy built Next.js app (including dist , node_modules, public, etc.)
71+ COPY --from=dotnet -build /src/TechStacks.Client ./client
5472
5573ENV ASPNETCORE_URLS=http://0.0.0.0:8080 \
74+ INTERNAL_API_URL=http://127.0.0.1:8080 \
5675 NEXT_PORT=3000 \
5776 NODE_ENV=production \
58- INTERNAL_API_URL=http://127.0.0.1:8080 \
59- SERVICESTACK_LICENSE=$SERVICESTACK_LICENSE
77+ SERVICESTACK_LICENSE=$SERVICESTACK_LICENSE \
78+ KAMAL_DEPLOY_HOST=$KAMAL_DEPLOY_HOST
6079
6180EXPOSE 8080
6281
0 commit comments