Dotnet Core+Angular Universal多阶段Docker构建预渲染失败问题
解决Angular Universal + .NET Core多阶段Docker构建预渲染模块缺失问题
我之前在做Angular Universal和.NET Core的Docker化时,也踩过几乎一模一样的坑!咱们先把问题根源说清楚:你的多阶段构建只复制了编译后的.NET发布产物和Angular的dist文件,但服务器端预渲染依赖的Node.js模块并没有被同步到运行容器里。单容器模式下因为构建和运行环境是同一个,node_modules本来就存在,所以能正常跑;但多阶段构建时,你漏掉了生产环境所需的npm依赖,导致预渲染时找不到angular2-universal-polyfills这类核心模块。
修正后的多阶段Dockerfile
# 第一阶段:构建.NET和Angular应用 FROM buildpack-deps:jessie-scm AS builder # 安装.NET Core SDK RUN apt-get update \ && apt-get install -y --no-install-recommends \ libc6 \ libcurl3 \ libgcc1 \ libgssapi-krb5-2 \ libicu52 \ liblttng-ust0 \ libssl1.0.0 \ libstdc++6 \ libunwind8 \ libuuid1 \ zlib1g \ && rm -rf /var/lib/apt/lists/* ENV DOTNET_SDK_VERSION 2.1.200 ENV DOTNET_SDK_DOWNLOAD_URL https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz ENV DOTNET_SDK_DOWNLOAD_SHA c1b07ce8849619ca505aafd2983bcdd7141536ccae243d4249b0c9665daf107e03a696ad5f1d95560142cd841a0888bbf5f1a8ff77d3bdc3696b5873481f0998 RUN curl -SL $DOTNET_SDK_DOWNLOAD_URL --output dotnet.tar.gz \ && echo "$DOTNET_SDK_DOWNLOAD_SHA dotnet.tar.gz" | sha512sum -c - \ && mkdir -p /usr/share/dotnet \ && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \ && rm dotnet.tar.gz \ && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet ENV DOTNET_RUNNING_IN_CONTAINER=true \ DOTNET_USE_POLLING_FILE_WATCHER=true \ NUGET_XMLDOC_MODE=skip # 预热.NET环境 RUN mkdir warmup \ && cd warmup \ && dotnet new \ && cd .. \ && rm -rf warmup \ && rm -rf /tmp/NuGetScratch # 安装Node.js和Angular CLI ENV NODE_VERSION="8.11.0" RUN apt-get install wget -y \ && set -ex \ && for key in \ 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ 0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \ FD3A5288F042B6850C66B31F09FE44734EB7990E \ 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ B9AE9905FFD7803F25714661B63B535A4C206CA9 \ C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \ 77984A986EBC2AA786BC0F66B01FBB92821C587A \ 56730D5401028683275BD23C23EFEFE93C4CFFFE \ ; do \ gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \ done \ && wget "https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -O node-v$NODE_VERSION-linux-x64.tar.gz \ && wget "https://nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt.asc" -O SHASUMS256.txt.asc \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 \ && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN npm config set user 0 \ && npm config set unsafe-perm true \ && npm install -g @angular/cli@1.7.4 # 复制项目文件并构建 WORKDIR /app COPY . . RUN dotnet restore ./CodefictionApi RUN dotnet publish ./CodefictionApi -c Release -o /publish # 第二阶段:运行容器(仅包含生产环境依赖) FROM microsoft/aspnetcore:2.0 AS runtime WORKDIR /app EXPOSE 80 # 在运行容器中安装Node.js(仅生产环境需要) ENV NODE_VERSION="8.11.0" RUN apt-get update \ && apt-get install -y --no-install-recommends wget \ && set -ex \ && for key in \ 94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \ 0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \ FD3A5288F042B6850C66B31F09FE44734EB7990E \ 71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \ DD8F2338BAE7501E3DD5AC78C273792F7D83545D \ B9AE9905FFD7803F25714661B63B535A4C206CA9 \ C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \ 77984A986EBC2AA786BC0F66B01FBB92821C587A \ 56730D5401028683275BD23C23EFEFE93C4CFFFE \ ; do \ gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \ done \ && wget "https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -O node-v$NODE_VERSION-linux-x64.tar.gz \ && wget "https://nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt.asc" -O SHASUMS256.txt.asc \ && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \ && grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt | sha256sum -c - \ && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 \ && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc SHASUMS256.txt \ && ln -s /usr/local/bin/node /usr/local/bin/nodejs \ && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/* # 复制发布产物、package.json并安装生产环境npm依赖 COPY --from=builder /publish . COPY --from=builder /app/package.json . COPY --from=builder /app/package-lock.json . RUN npm install --production # 设置入口点 ENTRYPOINT ["dotnet", "CodefictionApi.dll"]
关键修复点解释
- 拆分构建与运行阶段:第一阶段负责完整构建(包含SDK、Node.js、开发依赖),第二阶段只保留生产环境需要的.NET运行时、Node.js运行时和生产依赖,大幅缩小容器体积。
- 复制npm依赖清单:把
package.json和package-lock.json从构建阶段复制到运行阶段,执行npm install --production安装预渲染必需的生产依赖(比如angular2-universal-polyfills)。 - 保持Node.js版本一致:构建和运行阶段使用相同版本的Node.js,避免因环境不一致导致的模块兼容问题。
这样构建出来的容器体积会远小于2GB,同时能完美解决预渲染时的模块缺失问题。
内容的提问来源于stack exchange,提问作者Deniz Örgin
相关产品推荐
相关产品推荐

