Skip to content

Update spa templates to facilitate multi-stage docker builds #41275

Closed as not planned
dotnet/spa-templates
#58
@tmds

Description

@tmds

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

The spa templates use npm for the client-side, and dotnet for the server-side.

The .NET sdk container images do not provide npm. So they can not be used directly to build the spa templates.

Another option is to use a multi-stage build, with a separate stage that uses a node image. The templates are not written to support this scenario.

Describe the solution you'd like

With some tweaks to the template, the project can more easily support a multi-stage build that has a node/npm stage.

$ dotnet new angular -o angular
$ cd angular

Modify the csproj:

     <Nullable>enable</Nullable>
     <IsPackable>false</IsPackable>
     <SpaRoot>ClientApp\</SpaRoot>
+    <SpaBuildCommand>npm run build -- --prod</SpaBuildCommand>
     <SpaProxyServerUrl>https://localhost:44411</SpaProxyServerUrl>
     <SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
     <ImplicitUsings>enable</ImplicitUsings>
@@ -33,8 +34,8 @@
   
   <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
     <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
-    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
-    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
+    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" Condition="'$(SkipSpaBuild)' != 'True'"/>
+    <Exec WorkingDirectory="$(SpaRoot)" Command="$(SpaBuildCommand)" Condition="'$(SkipSpaBuild)' != 'True'"/>
 
     <!-- Include the newly-built files in the publish output -->
     <ItemGroup>

This app can be built using the following multi-stage Dockerfile:

# Publish Spa
FROM node:lts-alpine as node-build
WORKDIR /src
COPY . ./
# cd to csproj <SpaRoot>
WORKDIR /src/ClientApp
# restore npm dependencies
RUN npm install
# run csproj <SpaBuildCommand>
RUN npm run build -- --prod

# Publish application
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS dotnet-build
USER 0
WORKDIR /src
COPY . ./
# Copy SpaRoot
COPY --from=node-build /src/ClientApp /src/ClientApp
RUN dotnet restore .
# Skip Spa build during publish
RUN dotnet publish --no-restore -c Release -o /out . /p:SkipSpaBuild=True

# Build application image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
COPY --from=dotnet-build /out /app
CMD ["dotnet", "/app/angular.dll"]

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesfeature-spa

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions