dotnet core + Angular Universal + docker => Преследование невозможно из-за ошибки: Ошибка: не удается найти модуль

У нас есть проект, разработанный с использованием ядра Dotnet, Angular Universal. Мы используем функцию prerender для сервисов Asp.net Core SPA. В локальной среде приложение работает как в Windows, так и в Linux. Там есть некоторые проблемы при использовании шаблона многоэтапной сборки для докеры Visual Studio. После того, как мы построим его в файле microsoft/aspnetcore-build, мы передаем файлы в файл microsoft/aspnetcore. Из-за зависимости Asp.net SPA от nodejs мы также устанавливаем nodejs в образ microsoft/aspnetcore.

Но когда мы запускаем приложение, мы получаем сообщение об ошибке "Prerendering failed из-за ошибки: Ошибка: не удается найти модуль" angular2-universal-polyfills "на стадии prerender main.bundle.js (на стороне сервера). Мы уверены, что проблема не связана с "angular2-universal-polyfills", потому что мы также пробовали другие полиполки и получили аналогичные ошибки.

Но когда мы устанавливаем как.net-ядро, так и nodejs в один контейнер вместо многоэтапной сборки и выполняем сборку и публикацию операций внутри одного и того же контейнера, наше приложение работает. Но тогда размер контейнера составляет 2 ГБ.

Теоретически, нет разницы между контейнером, который мы строим, и контейнером, который мы запускаем. Оба имеют оба ядра.net и nodejs. Единственное отличие заключается в том, что мы копируем публикацию вывода в контейнер, который мы запускаем.

Опубликовать вывод

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

Рабочий файл докеров

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"]

Многоступенчатый файл докеров (который дает ошибку prerender при запуске)

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

  <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>

Полный источник может быть проверен здесь

https://github.com/Blind-Striker/codefiction-tech-new

Не рабочая версия может быть проверена из этой ветки

https://github.com/Blind-Striker/codefiction-tech-new/tree/docker-not-working-version

Благодарю.

Ответ 1

angular2-universal-polyfills больше не существует. Это происходит, вероятно, при локальном запуске установки пакета из вашего локального кеша, но когда вы запускаете его в контейнере, он ищет в реестре npm и он терпит неудачу. Чтобы обновить проект, вы можете ознакомиться с этой ссылкой на github. У них есть хорошее объяснение, как мигрировать.