Docker化引用同解决方案内项目的API遇构建报错,如何解决?
问题
我有一个名为PostalCode的解决方案,包含三个项目:
- 核心类库PostalCode.Core(包含数据库、模型及服务)
- 引用Core并使用其服务的PostalCode.API
- 作为UI层且引用API并调用接口的PostalCode.MVC
我已成功为MVC项目编写Dockerfile并完成Docker化,其内容如下:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 4420 # Use the official SDK image to build the project FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY . . RUN dotnet restore "PostalCode.MVC.csproj" RUN dotnet publish "PostalCode.MVC.csproj" -c Release -o /app/publish # Final image with published output FROM base AS final WORKDIR /app COPY --from=build /app/publish . ENTRYPOINT ["dotnet", "PostalCode.MVC.dll"]
但将该Dockerfile修改为适配API项目(替换PostalCode.MVC为PostalCode.API)后,出现如下构建错误:
ERROR [build 5/5] RUN dotnet publish "PostalCode.API.csproj" -c Release -o /app/publish failed to solve: failed to compute cache key: failed to calculate checksum of ref 50ec7a5e-e296-49d7-87c1-66dffd6e00da::go8tj6phckvpcr0ab9qaxo4z9: "/PostalCode.API/PostalCode.API.csproj": not found
请问代码存在什么问题?编写API的Dockerfile时是否需要包含对Core项目的引用?
解答
问题根源
构建失败的核心原因是Docker上下文路径与项目文件路径不匹配:
- 之前MVC项目的Dockerfile能正常工作,是因为你大概率将Dockerfile放在了MVC项目的根目录下,
COPY . .会把MVC项目的所有文件复制到容器的/src目录,能直接找到PostalCode.MVC.csproj。 - 修改为API项目时,你只是替换了项目名称,但没有调整Dockerfile中的路径逻辑,也没有确认Docker构建上下文是否正确,导致容器内找不到
PostalCode.API.csproj文件。
修复方案
根据你的解决方案结构,推荐两种标准的Dockerfile编写方式:
方式1:在解决方案根目录编写API的Dockerfile
如果你的解决方案目录结构如下:
PostalCode/ ├── PostalCode.sln ├── PostalCode.Core/ ├── PostalCode.API/ │ └── PostalCode.API.csproj └── PostalCode.MVC/
将Dockerfile放在解决方案根目录,内容如下:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # 先复制项目文件,利用Docker缓存优化构建速度 COPY ["PostalCode.API/PostalCode.API.csproj", "PostalCode.API/"] COPY ["PostalCode.Core/PostalCode.Core.csproj", "PostalCode.Core/"] # 还原API项目的所有依赖(包括Core) RUN dotnet restore "PostalCode.API/PostalCode.API.csproj" # 复制所有源代码 COPY . . WORKDIR "/src/PostalCode.API" # 发布API项目 RUN dotnet publish "PostalCode.API.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=build /app/publish . ENTRYPOINT ["dotnet", "PostalCode.API.dll"]
方式2:在API项目根目录编写Dockerfile
将Dockerfile放在PostalCode.API/目录下,内容调整为:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # 复制API和Core的项目文件(注意相对路径基于解决方案根目录) COPY ["PostalCode.API.csproj", "."] COPY ["../PostalCode.Core/PostalCode.Core.csproj", "../PostalCode.Core/"] RUN dotnet restore "PostalCode.API.csproj" # 复制所有源代码,构建时需指定上下文为解决方案根目录 COPY . . WORKDIR "/src" RUN dotnet publish "PostalCode.API.csproj" -c Release -o /app/publish FROM base AS final WORKDIR /app COPY --from=build /app/publish . ENTRYPOINT ["dotnet", "PostalCode.API.dll"]
这种方式下,执行构建命令时需要指定上下文为解决方案根目录:
docker build -t postalcode-api -f PostalCode.API/Dockerfile .
关于Core项目的引用
必须包含对Core项目的引用。因为PostalCode.API直接依赖PostalCode.Core,构建API时Docker需要访问到Core项目的源代码,才能完成编译(否则会因找不到Core的类和服务而编译失败)。上面两种方案都通过复制Core的项目文件和源代码,确保了构建过程中能正确解析依赖。
内容的提问来源于stack exchange,提问作者Aboliii
相关产品推荐
相关产品推荐

