ASP.NET Core Docker镜像构建时部分文件夹未复制的问题
ASP.NET Core Docker镜像构建中部分文件夹未复制问题排查
问题背景
构建ASP.NET Core Web应用Docker镜像时,出现MyNotes文件夹未被复制到最终镜像的异常,仅MyData文件夹存在。相关Dockerfile及目标目录结构如下:
Dockerfile内容
FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build WORKDIR /src COPY ["Nuget.config", "."] COPY ["MyProject/MyProject.csproj", "MyProject/"] RUN dotnet restore "MyProject/MyProject.csproj" --configfile /src/Nuget.config COPY . . WORKDIR /src/MyProject RUN dotnet build "MyProject.csproj" -c Release -o /app/build --configfile /src/Nuget.config RUN mkdir -p /app/publish/MyNotes RUN mkdir -p /app/publish/MyData RUN cp -R "../packages/mylibrary/2.0.3/lib/netstandard2.0/MyNotes" "/app/publish/" RUN cp -R "../packages/mylibrary/2.0.3/lib/netstandard2.0/MyData" "/app/publish/" #COPY ["../packages/mylibrary/2.0.3/lib/netstandard2.0/MyNotes", "/app/publish/MyNotes"] #COPY ["../packages/mylibrary/2.0.3/lib/netstandard2.0/MyNotes/ps/", "/app/publish/MyNotes/ps/"] #COPY ["../packages/mylibrary/2.0.3/lib/netstandard2.0/MyNotes/pc/", "/app/publish/MyNotes/pc/"] #COPY ["../packages/mylibrary/2.0.3/lib/netstandard2.0/MyData", "/app/publish/MyData"] FROM build AS publish RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish --no-restore FROM base AS final WORKDIR /app COPY --from=publish /app/publish . RUN find . -type f ENTRYPOINT ["dotnet", "MyProject.dll"]
目标目录结构
MyNotes |_ pc |_ example1.txt |_ example2.txt |_ ps |_ example4.txt MyData |_ example7.txt
异常现象
- 构建阶段执行
RUN find . -type f显示两个文件夹已复制 - 镜像运行后进入容器执行
ls,仅MyData存在,MyNotes文件夹缺失 - 使用注释中的
COPY命令也出现相同问题
问题根源
publish阶段的dotnet publish命令会完全覆盖/app/publish目录。
你在build阶段手动将MyNotes和MyData复制到了/app/publish,但后续执行dotnet publish时,该命令会将编译后的项目输出写入/app/publish,直接覆盖之前手动复制的内容。MyData之所以保留,大概率是因为你的项目本身包含MyData目录,dotnet publish会自动将其复制到发布目录,而MyNotes不在项目范围内,所以被覆盖后消失。
修复方案
方案一:调整复制顺序,在publish完成后执行复制
将手动复制文件夹的操作移到publish阶段之后,避免被dotnet publish覆盖:
FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build WORKDIR /src COPY ["Nuget.config", "."] COPY ["MyProject/MyProject.csproj", "MyProject/"] RUN dotnet restore "MyProject/MyProject.csproj" --configfile /src/Nuget.config COPY . . WORKDIR /src/MyProject RUN dotnet build "MyProject.csproj" -c Release -o /app/build --configfile /src/Nuget.config FROM build AS publish RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish --no-restore # 将复制操作移到publish命令之后 RUN cp -R "../packages/mylibrary/2.0.3/lib/netstandard2.0/MyNotes" "/app/publish/" RUN cp -R "../packages/mylibrary/2.0.3/lib/netstandard2.0/MyData" "/app/publish/" FROM base AS final WORKDIR /app COPY --from=publish /app/publish . RUN find . -type f ENTRYPOINT ["dotnet", "MyProject.dll"]
方案二:通过项目配置自动复制依赖文件(推荐)
修改项目文件MyProject.csproj,让dotnet publish自动将依赖文件复制到发布目录,无需手动操作:
<Project Sdk="Microsoft.NET.Sdk.Web"> <!-- 保留原有配置 --> <ItemGroup> <!-- 添加以下配置,指定要复制的文件 --> <Content Include="..\packages\mylibrary\2.0.3\lib\netstandard2.0\MyNotes\**"> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <Link>MyNotes\%(RecursiveDir)%(Filename)%(Extension)</Link> </Content> <Content Include="..\packages\mylibrary\2.0.3\lib\netstandard2.0\MyData\**"> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <Link>MyData\%(RecursiveDir)%(Filename)%(Extension)</Link> </Content> </ItemGroup> </Project>
修改后,删除Dockerfile中所有手动复制MyNotes和MyData的命令,dotnet publish会自动完成文件复制。
内容的提问来源于stack exchange,提问作者Snake Eyes
相关产品推荐
相关产品推荐

