Reputation: 607
We have a project developed using Dotnet core, Angular Universal. We use the prerender feature of Asp.net Core SPA services. In the local environment, the application works both on Windows, Linux. There some problems when using Visual Studio's own docker multi-stage build template. After we build it in microsoft/ aspnetcore-build image, we transfer the files to microsoft/aspnetcore image. Because of the dependency of Asp.net SPA's to nodejs, we also install nodejs to microsoft/aspnetcore image.
But when we run the application, we are getting the error "Prerendering failed because of error: Error: Can not find module 'angular2-universal-polyfills'" at the prerender stage of main.bundle.js (server-side). We are confident that the problem is not related to 'angular2-universal-polyfills' because we have also tried other polyfills and got similar errors.
But when we install both .net core and nodejs into a single container instead of multi-stage build and do build and publish operations inside the same container, our application works. But then the container is 2 GB in size.
Theoretically, there is no difference between the container we build and the container we run. Both have both .net core and nodejs installed. The only difference is we copy publish output to the container that we run.
Publish output
root
wwwroot (angular client-side dist)
assets
inline.bundle.js
main.bundle.js
polyfill.bundle.js
vendor.bundle.js
CodefictionApp/dist-server (angular server-side dist)
assets
main.bundle.js
dlls
Working Dockerfile
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM buildpack-deps:jessie-scm
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
RUN mkdir warmup \
&& cd warmup \
&& dotnet new \
&& cd .. \
&& rm -rf warmup \
&& rm -rf /tmp/NuGetScratch
ENV RestoreUseSkipNonexistentTargets false
ENV NODE_VERSION="8.11.0"
RUN apt-get install wget -y
RUN 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
RUN set -ex \
&& 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
RUN npm config set unsafe-perm true
RUN npm install -g @angular/[email protected]
RUN node -v && npm -v && ng -v
RUN apt-get update && apt-get install bzip2 -y
ENV ASPNETCORE_URLS http://+:80
WORKDIR /app
EXPOSE 80
COPY . .
RUN dotnet restore ./CodefictionApi
RUN dotnet publish ./CodefictionApi -c Release
WORKDIR /app/CodefictionApi/bin/Release/netcoreapp2.0/publish
ENTRYPOINT ["dotnet", "CodefictionApi.dll"]
Multi-stage docker file (whic gives prerender error when its run)
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM buildpack-deps:jessie-scm AS publisher
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
RUN mkdir warmup \
&& cd warmup \
&& dotnet new \
&& cd .. \
&& rm -rf warmup \
&& rm -rf /tmp/NuGetScratch
ENV RestoreUseSkipNonexistentTargets false
ENV NODE_VERSION="8.11.0"
RUN apt-get install wget -y
RUN 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
RUN set -ex \
&& 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
RUN npm config set unsafe-perm true
RUN npm install -g @angular/[email protected]
RUN node -v && npm -v && ng -v
RUN apt-get update && apt-get install bzip2 -y
ENV ASPNETCORE_URLS http://+:80
WORKDIR /app
COPY . .
RUN dotnet restore ./CodefictionApi
RUN dotnet publish ./CodefictionApi -c Release
FROM base AS final
ARG source
EXPOSE 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_8.x | bash -
RUN apt-get install -y nodejs
RUN npm config set user 0
RUN npm config set unsafe-perm true
RUN npm install -g npm
RUN npm install -g @angular/[email protected] --unsafe
RUN npm install -g @angular/[email protected]
RUN node -v && npm -v && ng -v
ENV ASPNETCORE_ENVIRONMENT=Development
WORKDIR /app/CodefictionApi/bin/Release/netcoreapp2.0/publish
COPY --from=publisher /app/CodefictionApi/bin/Release/netcoreapp2.0/publish .
ENTRYPOINT ["dotnet", "CodefictionApi.dll"]
package.json
{
"name": "codefiction-app",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/cli": "~1.7.4",
"@angular/animations": "^5.0.0",
"@angular/common": "^5.0.0",
"@angular/compiler": "^5.0.0",
"@angular/core": "^5.0.0",
"@angular/forms": "^5.0.0",
"@angular/http": "^5.0.0",
"@angular/platform-browser": "^5.0.0",
"@angular/platform-browser-dynamic": "^5.0.0",
"@angular/platform-server": "^5.0.0",
"@angular/router": "^5.2.1",
"@nguniversal/aspnetcore-engine": "^5.0.0",
"@nguniversal/common": "^5.0.0",
"@types/node": "^7.0.12",
"angular2-router-loader": "^0.3.5",
"angular2-template-loader": "^0.6.2",
"angular2-universal-polyfills": "2.0.11",
"aspnet-prerendering": "3.0.1",
"awesome-typescript-loader": "^3.0.0",
"bootstrap": "^3.3.7",
"bootstrap-sass": "^3.3.7",
"core-js": "^2.5.1",
"css": "^2.2.1",
"css-loader": "^0.28.7",
"event-source-polyfill": "^0.0.9",
"file-loader": "^0.11.2",
"html-loader": "^0.5.1",
"isomorphic-fetch": "^2.2.1",
"jquery": "^2.2.1",
"json-loader": "^0.5.4",
"moment": "2.18.1",
"node-sass": "^4.5.2",
"preboot": "6.0.0-beta.0",
"raw-loader": "^0.5.1",
"rimraf": "^2.6.2",
"rxjs": "^5.5.6",
"style-loader": "^0.18.2",
"to-string-loader": "^1.1.5",
"typescript": "~2.5.0",
"url-loader": "^0.5.7",
"zone.js": "^0.8.4"
},
"devDependencies": {
"@angular/compiler-cli": "^5.2.1",
"@types/chai": "^3.4.34",
"@types/jasmine": "^2.5.37",
"chalk": "^2.4.1",
"chai": "^3.5.0",
"codelyzer": "4.0.0",
"jasmine-core": "^2.5.2",
"karma": "^1.7.1",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^2.2.0",
"karma-coverage": "^1.1.1",
"karma-jasmine": "^1.1.0",
"karma-mocha-reporter": "^2.2.4",
"karma-phantomjs-launcher": "^1.0.4",
"karma-remap-coverage": "^0.1.4",
"karma-sourcemap-loader": "^0.3.7",
"protractor": "~5.1.2",
"ts-node": "~4.1.0",
"tslint": "~5.9.1"
}
}
csproj publish command
<Target Name="PublishProject" BeforeTargets="ComputeFilesToPublish">
<Exec Command="npm install" />
<Exec Command="./node_modules/.bin/ng -v" />
<Exec Command="./node_modules/.bin/ng build --env=dev --app 0" />
<Exec Command="./node_modules/.bin/ng build --env=dev --app 1" />
<!-- Include the newly-built files in the publish output -->
<ItemGroup>
<DistFiles Include="wwwroot/**; CodefictionApp/dist-server/**" />
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
Full source can be inspected from here
https://github.com/Blind-Striker/codefiction-tech-new
Not working version can be inspected from this branch
https://github.com/Blind-Striker/codefiction-tech-new/tree/docker-not-working-version
Thanks.
Upvotes: 27
Views: 1286
Reputation: 641
angular2-universal-polyfills
module does not exist anymore. This is happening probably when you running locally its installing the package from your local cache but when you
are running it in container its looking in the npm registry and it fails.
To upgrade your project you can follow this link documentation on the github. They have nice explanation how to migrate.
Upvotes: 2