ASP.NET Core 3.1 + React.js + Docker で npm install や npm start が失敗する件
↓のページを参考に ASP.NET Core 3.1 + React.js + Docker を試していますが、Debug 構成での実行は (何故か) 出来るものの、Dockerfile のビルドを直接行ったり Release 構成での実行や発行を行うと失敗してしまいました。
原因は2つあって、一つは .NET Core SDK の Docker イメージに node.js が含まれていないことだと思われます。
1>Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core 1> 1>Copyright (C) Microsoft Corporation. All rights reserved. 1> Restore completed in 48.96 ms for /src/WebApplication1/WebApplication1.csproj. 1> WebApplication1 -> /src/WebApplication1/bin/Release/netcoreapp3.1/WebApplication1.dll 1> WebApplication1 -> /src/WebApplication1/bin/Release/netcoreapp3.1/WebApplication1.Views.dll 1> /bin/sh: 2: /tmp/tmpa4ca4172ac674b57a69cab6fbb18beea.exec.cmd: npm: not found 1>/src/WebApplication1/WebApplication1.csproj(38,5): error MSB3073: The command "npm install" exited with code 127. 1>Removing intermediate container 965d653d9ca2 1>The command '/bin/sh -c dotnet publish "WebApplication1.csproj" -c Release -o /app/publish' returned a non-zero code: 1 1>D:\source\repos\WebApplication1\WebApplication1\dockerfile : error CTC1014: Docker コマンドが終了コード 1 で失敗しました。 1>D:\source\repos\WebApplication1\WebApplication1\dockerfile : error CTC1014: The command '/bin/sh -c dotnet publish "WebApplication1.csproj" -c Release -o /app/publish' returned a non-zero code: 1 1>プロジェクト "WebApplication1.csproj" のビルドが終了しました -- 失敗。 ========== すべてリビルド: 0 正常終了、1 失敗、0 スキップ ==========
なので "base" ステージだけでなく "build" ステージでも node.js をインストールすることで解決します。
(関係無いですが、ついでに Node.js のバージョンは 12.x 系に上げてます。)
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base WORKDIR /app EXPOSE 80 EXPOSE 443 RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - RUN apt-get install -y nodejs FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build WORKDIR /src RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - RUN apt-get install -y nodejs COPY ["WebApplication1/WebApplication1.csproj", "WebApplication1/"] RUN dotnet restore "WebApplication1/WebApplication1.csproj" COPY . . WORKDIR "/src/WebApplication1" RUN dotnet build "WebApplication1.csproj" -c Release -o /app/build FROM build AS publish RUN dotnet publish "WebApplication1.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "WebApplication1.dll"]
もう一つは、React の開発用サーバー起動時に Node.js が package.json を見つけられないことです。
An unhandled exception has occurred while executing the request. System.AggregateException: One or more errors occurred. (One or more errors occurred. (The NPM script 'start' exited without indicating that the create-react-app server was listening for requests. The error output was: npm ERR! code ENOENT npm ERR! syscall open npm ERR! path /app/ClientApp/package.json npm ERR! errno -2 npm ERR! enoent ENOENT: no such file or directory, open '/app/ClientApp/package.json' npm ERR! enoent This is related to npm not being able to find a file. npm ERR! enoent npm ERR! A complete log of this run can be found in: )) ---> System.AggregateException: One or more errors occurred. (The NPM script 'start' exited without indicating that the create-react-app server was listening for requests. The error output was: npm ERR! code ENOENT npm ERR! syscall open npm ERR! path /app/ClientApp/package.json npm ERR! errno -2 npm ERR! enoent ENOENT: no such file or directory, open '/app/ClientApp/package.json' npm ERR! enoent This is related to npm not being able to find a file. npm ERR! enoent npm ERR! A complete log of this run can be found in: ) ---> System.InvalidOperationException: The NPM script 'start' exited without indicating that the create-react-app server was listening for requests. The error output was: npm ERR! code ENOENT npm ERR! syscall open npm ERR! path /app/ClientApp/package.json npm ERR! errno -2 npm ERR! enoent ENOENT: no such file or directory, open '/app/ClientApp/package.json' npm ERR! enoent This is related to npm not being able to find a file. npm ERR! enoent npm ERR! A complete log of this run can be found in: ---> System.IO.EndOfStreamException: Attempted to read past the end of the stream. at Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer.ReactDevelopmentServerMiddleware.StartCreateReactAppServerAsync(String sourcePath, String npmScriptName, ILogger logger) --- End of inner exception stack trace --- at Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer.ReactDevelopmentServerMiddleware.StartCreateReactAppServerAsync(String sourcePath, String npmScriptName, ILogger logger) --- End of inner exception stack trace --- at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task`1.get_Result() at Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer.ReactDevelopmentServerMiddleware.<>c.<Attach>b__2_0(Task`1 task) at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke() at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj) at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location where exception was thrown --- at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) --- End of inner exception stack trace --- at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task`1.get_Result() at Microsoft.AspNetCore.SpaServices.Extensions.Util.TaskTimeoutExtensions.WithTimeout[T](Task`1 task, TimeSpan timeoutDelay, String message) at Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task`1 baseUriTask, CancellationToken applicationStoppingToken, Boolean proxy404s) at Microsoft.AspNetCore.Builder.SpaProxyingExtensions.<>c__DisplayClass2_0.<<UseProxyToSpaDevelopmentServer>b__0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
こちらは今のところ直接的な解決方法はわかっていませんが、React の開発用サーバーを使わないよう Startup.cs を変更することで回避は可能なようです。
app.UseSpa(spa => { spa.Options.SourcePath = "ClientApp"; //if (env.IsDevelopment()) //{ // spa.UseReactDevelopmentServer(npmScript: "start"); //} });