最稳路径是dotnet publish+多阶段dockerfile:用sdk镜像构建、runtime/aspnet镜像运行,主版本严格对齐(如全用8.0),entrypoint指向publish输出的.dll而非.csproj,并设aspnetcore_urls=http://+:80、workdir匹配copy路径、.dockerignore排除bin/obj等。

最稳的路径是 dotnet publish + 多阶段 Dockerfile,用 sdk 镜像构建、runtime 或 aspnet 镜像运行,主版本号(如 8.0)必须严格对齐,否则容器一启动就报 Could not load file or assembly 或 It was not possible to find any compatible framework version。
ENTRYPOINT 必须指向 .dll,不是 .csproj
常见错误是写成 ENTRYPOINT ["dotnet", "MyApp.csproj"]——容器里没有 SDK,.csproj 不是可执行体。真正该用的是 dotnet publish -c Release -o ./publish 输出目录里的 MyApp.dll(文件名默认与项目名一致,除非改过 AssemblyName)。
确保以下三者匹配:
-
dotnet publish的输出路径(如./publish) -
Dockerfile中COPY --from=build-env /app/publish .的源路径 -
WORKDIR /app后的ENTRYPOINT ["dotnet", "MyApp.dll"]
SDK 和 Runtime 镜像版本不一致直接启动失败
混用 mcr.microsoft.com/dotnet/sdk:8.0 和 mcr.microsoft.com/dotnet/aspnet:7.0 是高频翻车点。错误信息通常是共享框架缺失或 JSON 序列化行为异常——.NET 主版本不一致会导致运行时行为差异,不是“差不多能跑”。
验证方式:
- 构建后运行:
docker run --rm <your-image> dotnet --list-runtimes</your-image> - 输出中必须含
Microsoft.AspNetCore.App 8.0.x(Web 项目)或Microsoft.NETCore.App 8.0.x(控制台/Worker) - 优先选带
-jammy后缀的镜像(如aspnet:8.0-jammy),避免-focal在新版 Docker Desktop 上因 glibc 不兼容而启动失败
ASPNETCORE_URLS 和 ASPNETCORE_ENVIRONMENT 容器内常被忽略
本地 appsettings.Development.json 不会自动加载;没设 ASPNETCORE_ENVIRONMENT,配置就回退到默认值,数据库连接串、JWT 密钥全错位。
端口暴露靠两件事共同生效:
-
EXPOSE 80只是声明,不实际绑定 - 必须加环境变量:
ENV ASPNETCORE_URLS=http://+:80(Web 项目)或--urls http://+:80参数 - 宿主机访问需映射:
docker run -p 5000:80 <image></image>,左边是宿主机端口,右边是容器内监听端口
敏感配置别硬编码进 Dockerfile,改用 --env-file 或挂载配置文件(注意容器内路径要和 COPY 或 VOLUME 一致)。
.dockerignore 漏掉会泄露密钥还拖慢构建
不设 .dockerignore,docker build 会把整个项目目录(含 bin/、obj/、.git/、.user、NuGet.Config)打包进构建上下文,上传慢、镜像臃肿、还可能泄露本地 NuGet 缓存路径或用户密钥。
在项目根目录建 .dockerignore,至少包含:
.gitbin/obj/.vs/.user.env
检查构建日志里 Sending build context to Docker daemon 后面的大小,超过 100MB 就大概率漏了 ignore —— 这个数字比想象中更关键,也更容易被跳过。











