[{"data":1,"prerenderedAt":201},["ShallowReactive",2],{"/2025/12/06-aspnet-dockerfile-for-local-and-cicd":3},{"id":4,"title":5,"body":6,"date":192,"description":55,"extension":193,"meta":194,"navigation":195,"path":196,"robots":197,"seo":198,"stem":199,"__hash__":200},"posts/2025/12/06 aspnet-dockerfile-for-local-and-cicd.md","06 Aspnet Dockerfile For Local And Cicd",{"type":7,"value":8,"toc":189},"minimark",[9,18,21,25,27,42,56,58,61,69,71,87,89,104,112,114,117,125,127,135,143,146,154,156,169,177,179],[10,11,13],"post-title",{":date":12},"date",[14,15,17],"h1",{"id":16},"aspnet-dockerfile-for-local-and-cicd","ASP.NET Dockerfile for Local and CI/CD",[19,20],"br",{},[22,23,24],"p",{},"Finally my application is ready to be deployed. To make it portable, it needs to be containerized, so I'm working on Dockerfile.",[19,26],{},[22,28,29,30,41],{},"To get a jumpstart, I copied the Dockerfile from ",[31,32,35],"span",{"className":33},[34],"text-blue-600",[36,37,38],"a",{"href":38,"rel":39},"https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-10.0#the-dockerfile",[40],"nofollow",". Then I'm thinking to test it locally with the following command:",[43,44,45],"code-block",{},[46,47,52],"pre",{"className":48,"code":50,"language":51},[49],"language-text","docker build -t app:latest .\n","text",[53,54,50],"code",{"__ignoreMap":55},"",[19,57],{},[22,59,60],{},"However, it throws few error messages:",[43,62,63],{},[46,64,67],{"className":65,"code":66,"language":51},[49],"error MSB4018: The \"ResolvePackageAssets\" task failed unexpectedly.\n\nerror MSB4018: NuGet.Packaging.Core.PackagingException: Unable to find fallback package folder 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages'\n",[53,68,66],{"__ignoreMap":55},[19,70],{},[22,72,73,74,81,82,86],{},"Ok, it's weird that it's looking for windows path when the image is linux based. I quickly found out that since the COPY step runs locally, it copies the ",[53,75,80],{"className":76},[77,78,79],"bg-gray-200","p-2","rounded","bin"," and ",[53,83,85],{"className":84},[77,78,79],"obj"," directories as well which was generated from my local Windows machine and thus incompatible with the Linux based image.",[19,88],{},[22,90,91,92,96,97],{},"To prevent that, I tried using ",[53,93,95],{"className":94},[77,78,79],".dockerignore"," file and place it on the same directory as the Dockerfile. Since in dockerignore file, leading and trailing slashes are disregarded, I just need the following content. For more information: ",[31,98,100],{"className":99},[34],[36,101,102],{"href":102,"rel":103},"https://docs.docker.com/build/concepts/context/#syntax",[40],[43,105,106],{},[46,107,110],{"className":108,"code":109,"language":51},[49],"*/bin\n*/obj\n",[53,111,109],{"__ignoreMap":55},[19,113],{},[22,115,116],{},"Re-building it locally throws yet another error:",[43,118,119],{},[46,120,123],{"className":121,"code":122,"language":51},[49],"error NETSDK1047: Assets file '/source/path/to/app/obj/project.assets.json' doesn't have a target for 'net10.0/linux-x64'. Ensure that restore has run and that you have included 'net10.0' in the TargetFrameworks for your project. You may also need to include 'linux-x64' in your project's RuntimeIdentifiers.\n",[53,124,122],{"__ignoreMap":55},[19,126],{},[22,128,129,130,134],{},"I checked the .csproj file of my application and it doesn't have ",[53,131,133],{"className":132},[77,78,79],"\u003CRuntimeIdentifier>linux-x64\u003C/RuntimeIdentifier>",". Probably because my local development machine is Windows. Since I need it to be able to run in both Windows (local) and Linux (remote), I tried the following:",[43,136,137],{},[46,138,141],{"className":139,"code":140,"language":51},[49],"\u003CRuntimeIdentifier>linux-x64;win-x64\u003C/RuntimeIdentifier>\n",[53,142,140],{"__ignoreMap":55},[22,144,145],{},"Which is supposed to be valid, but the build failed again. This time the message is:",[43,147,148],{},[46,149,152],{"className":150,"code":151,"language":51},[49],"The \"HasTrailingSlash\" function only accepts a scalar value, but its argument \"$(OutputPath)\" evaluates to \"bin\\Debug/net10.0/linux-x64;win-x64/\" which is not a scalar value.\n",[53,153,151],{"__ignoreMap":55},[19,155],{},[22,157,158,159,163,164,168],{},"Alright, removed ",[53,160,162],{"className":161},[77,78,79],"\u003CRuntimeIdentifier>"," tag. On CI/CD pipeline, I'll use the Dockerfile, for local development, I'll just use Visual Studio or dotnet CLI, so I can add ",[53,165,167],{"className":166},[77,78,79],"--os linux"," option to dotnet restore step. In the Dockerfile, it becomes:",[43,170,171],{},[46,172,175],{"className":173,"code":174,"language":51},[49],"...\nRUN dotnet restore --os linux\n...\n",[53,176,174],{"__ignoreMap":55},[19,178],{},[22,180,181,182,81,185,188],{},"Then it builds successfully on my local machine. Since ",[53,183,80],{"className":184},[77,78,79],[53,186,85],{"className":187},[77,78,79]," directories are not tracked by the version control, the CI/CD pipeline won't have to worry about them.",{"title":55,"searchDepth":190,"depth":190,"links":191},2,[],"2025-12-06T00:00:00.000Z","md",{},true,"/2025/12/06-aspnet-dockerfile-for-local-and-cicd",null,{"title":5,"description":55},"2025/12/06 aspnet-dockerfile-for-local-and-cicd","an9Ge20wCWbCuZ8j61NL3lrsjl2GWcD5DWt147mXEzs",1785167452276]