.NET Core Docker Image for SPA Applications

前端 未结 6 1501
鱼传尺愫
鱼传尺愫 2020-12-08 16:05

What is the correct Docker image to use when creating a new ASP.NET Core MVC app, specifically with the React/Redux (or other Node.js required) template? If not a specific i

相关标签:
6条回答
  • 2020-12-08 16:13

    The problem is that the base image in your dockerfile (microsoft/aspnetcore:latest) does not have node installed.

    So you have to install node so you can run the project. This is the dockerfile I came up with:

    FROM microsoft/aspnetcore:2.0
    ARG source
    EXPOSE 80 5102
    ENV ASPNETCORE_URLS http://*:80
    RUN apt-get -qq update && apt-get -qqy --no-install-recommends install wget gnupg \
        git \
        unzip
    
    RUN curl -sL https://deb.nodesource.com/setup_6.x |  bash -
    RUN apt-get install -y nodejs
    WORKDIR /app
    COPY ${source:-obj/Docker/publish} .
    ENTRYPOINT ["dotnet", "Project.dll"]
    

    Notice how on line 5 of the dockerfile I'm running a command to update apt-get. And then in line 8-9 node is installed to the docker image

    There is still a problem, hot module replacement from webpack does not work. Not even a full refresh works. I'm still looking in to it.

    UPDATE: so I looked into the hot module replacement problem, and it appears to be a limitation of docker for windows.

    The workaround is to configure webpack so it can tell the browser to poll for changes on a determined amount of time. See this link to see how to configure it

    UPDATE: Doing a little more research I found out that microsoft has an image you can use to build your project, it is called: microsoft/aspnetcore-build. This image has all the dependencies you need for building (including nodejs).

    So at the end, what I did was leave my Dockerfile as it was (with microsoft/aspnetcore:2.0 as base image), and created a new Dockerfile for development which references the build image I mentioned before. With the help of docker compose I switch Dockerfiles depending on the environment.

    This approach seems more convenient because when images are deployed to production environment they should have all its javascript code ready (in the case of a spa application with angular 2, react, etc), in other words they should not have a nodejs dependency, making them less heavy in size.

    0 讨论(0)
  • 2020-12-08 16:19

    Here an easy way to containerize SPA applications:

    First, we have to comment this two lines in csproj file in your application because it force us to install NodeJS in a docker container.

    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />
    

    Next, inside container, you only need ASP.NET Core runtime for running your application. However a Node Docker image is used for compile React client application. So you need a Dockerfile like this:

    FROM node as build-node
    WORKDIR /ClientApp
    # ClientApp folder contains all your react code
    COPY MyApp/ClientApp/package.json .
    COPY MyApp/ClientApp/package-lock.json .
    RUN npm install
    COPY MyApp/ClientApp/ . 
    # This command will generate build folder
    RUN npm run build
    
    FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
    WORKDIR /app
    ENV ASPNETCORE_ENVIRONMENT=Production
    COPY *.sln .
    
    # In next step you'll get an error if you didn't comment two lines mentioned above in csproj file
    COPY MyApp/MyApp.csproj ./MyApp 
    RUN dotnet restore
    COPY MyApp/. ./MyApp
    WORKDIR /app/MyApp
    RUN dotnet publish -c Release -o out
    
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
    WORKDIR /app
    
    # Here we get compile result from .net core application
    COPY --from=build /app/MyApp/out ./
    
    # Here we  get compile result for React app
    COPY --from=build-node /ClientApp/build ./ClientApp/build
    
    # Application port
    EXPOSE 5000
    ENTRYPOINT ["dotnet", "MyApp.dll"]
    
    0 讨论(0)
  • 2020-12-08 16:21

    Even if you're running ASP.NET Core 3.0 the base images from Microsoft still does not contain NodeJS. You must install NodeJS by yourself. Luckily it's not that hard.

    Here's how I solved it recently. Please note the Dockerfile is more like pseudo-code than fully functional, I stripped away most noise. It's installing version 10 of NodeJS, you can of course change that. Here are different node distributions you can install.

    FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
    WORKDIR /app
    
    FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
    
    # Install NodeJS 10
    RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
    RUN apt-get install -y nodejs
    
    RUN npm install
    RUN npm run test-docker
    RUN npm run build
    
    RUN dotnet restore...
    
    RUN dotnet test...
    
    FROM build AS publish
    RUN dotnet publish "Collector.Forms.Autogiro.Web.csproj" -c Release -o /app/publish
    
    FROM base AS final
    WORKDIR /app
    COPY --from=publish /app/publish .
    ENTRYPOINT ["dotnet", "Your.Web.dll"]
    
    0 讨论(0)
  • 2020-12-08 16:24

    Based on @Daniels answer above, running Visual Studio 2017 v15.4 and ASP.NET Core 2.0 on Docker, here are the changes you need to make to allow correct Production and Development behavior for SPA applications (in my case I'm using Angular):

    • Add a new Dockerfile to your project which is a copy of the original. Lets call it Dockerfile.Development. Modify as follows:

      FROM microsoft/aspnetcore:2.0
      ARG source
      
      # BEGIN MODIFICATION - Node is needed for development (but not production)
      RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
      RUN apt-get install --assume-yes nodejs
      # END MODIFICATION
      
      WORKDIR /app
      EXPOSE 80
      COPY ${source:-obj/Docker/publish} .
      ENTRYPOINT ["dotnet", "MyService.dll"]
      
    • Modify the docker-compose.override.yml file in your solution to use this new dockerfile in development. It'll look something like this:

      version: '3'
      
      services:
        myservice:
          environment:
            - ASPNETCORE_ENVIRONMENT=Development
          ports:
            - "80"
          build:
            dockerfile: Dockerfile.Development
      
    • Modify the webpack.config.js file in your project to enable watching for changes, as follows:

      const clientBundleConfig = merge(sharedConfig, {
        entry: { 'main-client': './ClientApp/boot.browser.ts' },
        output: { path: path.join(__dirname, clientBundleOutputDir) },
        // BEGIN MODIFICATION
        watch: isDevBuild,
        watchOptions: {
          poll: isDevBuild ? 1000 : false
        },
        // END MODIFICATION
        plugins: [
          new webpack.DllReferencePlugin({
              context: __dirname,
              manifest: require('./wwwroot/dist/vendor-manifest.json')
          })
        ].concat(isDevBuild ? [
      
    0 讨论(0)
  • 2020-12-08 16:24

    If you need to add just the node binary to your image you can copy what the microsoft/aspnetcore-build dockerfile does:

    ENV NODE_VERSION 6.10.3
    
    RUN set -ex \
      && for key in \
        9554F04D7259F04124DE6B476D5A82AC7E37093B \
        94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
        0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \
        FD3A5288F042B6850C66B31F09FE44734EB7990E \
        71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
        DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
        B9AE9905FFD7803F25714661B63B535A4C206CA9 \
        C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
      ; do \
        gpg --keyserver pgp.mit.edu --recv-keys "$key" || \
        gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key" || \
        gpg --keyserver keyserver.pgp.com --recv-keys "$key" ; \
      done
    
    # set up node
    RUN buildDeps='xz-utils' \
        && set -x \
        && apt-get update && apt-get install -y $buildDeps --no-install-recommends \
        && rm -rf /var/lib/apt/lists/* \
        && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
        && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
        && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
        && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
        && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
        && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
        && apt-get purge -y --auto-remove $buildDeps \
        && ln -s /usr/local/bin/node /usr/local/bin/nodejs
    

    This adds about ~42 MB to your image vs ~157 MB using apt-get.

    0 讨论(0)
  • 2020-12-08 16:30

    I got the Angular example template to work simply by installing nodejs into the base:

    FROM microsoft/aspnetcore:2.0 AS base
    RUN apt-get update && \
        apt-get install -y wget && \
        apt-get install -y gnupg2 && \
        wget -qO- https://deb.nodesource.com/setup_6.x | bash - && \
        apt-get install -y build-essential nodejs
    WORKDIR /app
    EXPOSE 80
    ... rest of Dockerfile ...
    

    Everything else (Webpack Hot swap) didn't throw an error.

    0 讨论(0)
提交回复
热议问题