Docker .NET Core - 解决方案中的多个项目

nic*_*wdy 6 docker .net-core

我是 Docker 的新手,我正在尝试容器化我的 WebAPI,它是包含多个项目的解决方案的一部分。这是我的文件夹结构

Solution
    -- RandomPersonPicker.Api
        -- .dockerignore
        -- .dockerfile
    -- RandomPersonPicker.Date
    -- RandomPersonPicker.Domain
    -- RandomPersonPicker.Tests
Run Code Online (Sandbox Code Playgroud)

这是我的 Docker 文件:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything else and build
COPY . ../
RUN dotnet publish -c Release -o out

# Build runtime image
FROM mcr.microsoft.com/dotnet/core/sdk:3.1
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "RandomPersonPicker.Api.dll"]
Run Code Online (Sandbox Code Playgroud)

我从 RandomPersonPicker.Api 文件夹运行这个命令

docker build -t aspnetapp
Run Code Online (Sandbox Code Playgroud)

最后这是我的堆栈跟踪:

Skipping project "/RandomPersonPicker.Data/RandomPersonPicker.Data.csproj" because it was not found.
  Skipping project "/RandomPersonPicker.Data/RandomPersonPicker.Data.csproj" because it was not found.
  Restore completed in 186.69 ms for /app/RandomPersonPicker.Api.csproj.
/usr/share/dotnet/sdk/3.1.101/Microsoft.Common.CurrentVersion.targets(1875,5): warning : The referenced project '../RandomPersonPicker.Data/RandomPersonPicker.Data.csproj' does not exist. [/app/RandomPersonPicker.Api.csproj]
CompositionRoot.cs(2,26): error CS0234: The type or namespace name 'Data' does not exist in the namespace 'RandomPersonPicker' (are you missing an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
CompositionRoot.cs(3,26): error CS0234: The type or namespace name 'Data' does not exist in the namespace 'RandomPersonPicker' (are you missing an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
Controllers/PersonController.cs(4,26): error CS0234: The type or namespace name 'Data' does not exist in the namespace 'RandomPersonPicker' (are you missing an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
Controllers/PersonController.cs(5,26): error CS0234: The type or namespace name 'Domain' does not exist in the namespace 'RandomPersonPicker' (are you missing an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
Controllers/PersonController.cs(23,39): error CS0246: The type or namespace name 'Person' could not be found (are you missing a using directive or an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
Controllers/PersonController.cs(31,27): error CS0246: The type or namespace name 'Person' could not be found (are you missing a using directive or an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
Controllers/PersonController.cs(15,26): error CS0246: The type or namespace name 'IPersonRepository' could not be found (are you missing a using directive or an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
Controllers/PersonController.cs(17,33): error CS0246: The type or namespace name 'IPersonRepository' could not be found (are you missing a using directive or an assembly reference?) [/app/RandomPersonPicker.Api.csproj]
The command '/bin/sh -c dotnet publish -c Release -o out' returned a non-zero code: 1
Run Code Online (Sandbox Code Playgroud)

我理解这个问题,docker 无法识别我的其他项目的命名空间,这会导致编译错误,但我不知道解决这个问题的好方法。

任何帮助,将不胜感激。

san*_*jat 13

在此类情况下,我发现将 Dockerfile 放在与解决方案 (.sln) 相同的文件夹中会更容易。因此,如果您有多个具有公共类库的项目,您可以轻松地在单独的 docker 文件中引用它们。您可以从 root -> root 复制所有内容,或者一一提及每个项目。

注意:这是 git 的根目录,因此 Dockerfile 也成为代码存储库的一部分。

虚拟项目示例:

ROOT FOLDER
    |--- MultiProject.sln
    |--- MultiProject (solution folder)
        |-- Api.Web (project folder)
            -- Api.Web.csproj
        |-- Api.Mobile (project folder)
            -- Api.Mobile.csproj
        |-- ClassLibrary1
        |-- ClassLibrary2
    |--- Api.Web.Dockerfile
    |--- Api.Mobile.Dockerfile
    |--- .gitignore (*just to highlight the root of source repo*)
Run Code Online (Sandbox Code Playgroud)

虚拟项目 Api.Web.Dockerfile:

注意:您可能需要重组 dockerfile 以适应您的分层风格。示例中显示的层具有单独的构建层和发布层。

#Use your choice of image as base. Mine is alpine! 
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build
WORKDIR /src
COPY . .

RUN dotnet restore "MultiProject/Api.Web.csproj"
WORKDIR "/src/."
COPY . .
RUN dotnet build "MultiProject/Api.Web.csproj" -c Release -o /app/build

FROM build as publish
RUN dotnet publish "MultiProject/Api.Web.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_URLS http://*:PORT_NUMBER
ENTRYPOINT ["dotnet", "Api.dll"]
Run Code Online (Sandbox Code Playgroud)

现在,如果我想为 Api.Mobile 创建另一个 dockerfile,从上面的示例中创建一个就非常简单了。


小智 1

尝试在不同的步骤中执行构建和发布步骤。您还需要在恢复和构建后复制文件

下面几行的东西

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore *.csproj
COPY . .
RUN dotnet build -c Release

# Copy everything else and build
COPY . ../
RUN dotnet publish -o out --no-build

# Build runtime image
FROM mcr.microsoft.com/dotnet/core/sdk:3.1
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "RandomPersonPicker.Api.dll"]
Run Code Online (Sandbox Code Playgroud)