Containerize ASP.NET that has additional Class Library project - asp.net

I want to containerize an ASP.NET app. the whole solution paths look like this
I have tried to write the Dockerfile like this
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build-env
WORKDIR /app
# Copy the project files
COPY . ./MyApp
# Copy the Infrastructure project file
COPY ../Infrastructure/ ./Infrastructure/
# Restore NuGet packages
RUN dotnet restore
# Build the solution
RUN dotnet build
# Publish the ASP.NET app to a directory called "app"
RUN dotnet publish -c Release -o /app
# Build the final image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
COPY --from=build-env /app .
# Expose the port and start the app
EXPOSE 80
ENTRYPOINT ["dotnet", "MyApp.dll"]
but I get an error
What am I doing wrong and how can I fix my Dockerfile? Do I have to move it to the ParentDirectory or something? Can I keep my current solution structure and still containerize this app?

Related

Docker wwwroot content doesn't appear in final image

community. Have some strange things happening with my docker config.
It is an asp.net core 6.0 project with angular 9 with webpack. Linux docker engine running on windows 11. The angular build step works as intended.
The problem is with the wwwroot folder that is being built separately in FROM node:12.12.0-alpine as node-build, and in the final step is copied to the final image by COPY --from=node-build /src/wwwroot/ /app/wwwroot. The line RUN echo $(ls wwwroot/dist) shows that everything is in place, but when I go to debug and look in the container itself there are no files in wwwroot in app. It is my first docker image, so it can have some stupid newbie mistakes that I can't see. I looked in the eShopOnContainers example and the config is almost the same. Spend some unpleasant days trying to fix this issue with no luck :(.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM node:12.12.0-alpine as node-build
WORKDIR /src
COPY SomeName.MyProj .
RUN npm install
RUN npm run dev
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["SomeName.MyProj/SomeName.MyProj.csproj", "SomeName.MyProj/"]
COPY ["SomeName.MyProj.Domain/SomeName.MyProj.Domain.csproj", "SomeName.MyProj.Domain/"]
COPY ["SomeName.MyProj.Shared/SomeName.MyProj.Shared.csproj", "SomeName.MyProj.Shared/"]
COPY ["SomeName.MyProj.Services/SomeName.MyProj.Services.csproj", "SomeName.MyProj.Services/"]
COPY ["SomeName.MyProj.StorageInterface/SomeName.MyProj.StorageInterface.csproj", "SomeName.MyProj.StorageInterface/"]
COPY ["SomeName.MyProj.Storage/SomeName.MyProj.Storage.csproj", "SomeName.MyProj.Storage/"]
RUN dotnet restore "SomeName.MyProj/SomeName.MyProj.csproj"
COPY . .
WORKDIR /src/SomeName.MyProj
RUN dotnet build "SomeName.MyProj.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "SomeName.MyProj.csproj" -c Release -o /app /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
COPY --from=node-build /src/wwwroot/ /app/wwwroot
WORKDIR /app
RUN echo $(ls wwwroot/dist)
ENTRYPOINT ["dotnet", "SomeName.MyProj.dll"]

how to permanently remove source code reference in a .net core application

I have a .net core application that is compiled in release. I assumed that there wouldn't be any source information available.
but then I see the exception:
Unhandled exception. System.Exception: can't download the license data
at Common.Credentials.RequestCredentials[a](a licenseId) in /src/Weatherman/Common/Credentials.fs:line 71
so, the file names and lines are somehow bundled with the app.
the build is done like this (through a dockerfile):
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as build
WORKDIR /src/
COPY ./Weatherman/Common/Common.fsproj ./Weatherman/Common/Common.fsproj
COPY ./Weatherman/Exchange/Exchange.fsproj ./Weatherman/Exchange/Exchange.fsproj
COPY ./Services/Connector/Connector.fsproj ./Services/Connector/Connector.fsproj
RUN dotnet restore Services/Connector/Connector.fsproj
COPY . /src/
RUN dotnet build --nologo -c Release -o /app --no-restore Services/Connector/Connector.fsproj
FROM build AS publish
RUN dotnet publish --nologo -c Release -o /app --no-restore Services/Connector/Connector.fsproj
FROM mcr.microsoft.com/dotnet/core/runtime:3.1 as final
WORKDIR /app
COPY --from=publish /app .
so I really assumed that there wouldn't be any debug information left. How can I fix this?
You can configure your project to not produce debug information. You can add this to all your project files, or to a Directory.Build.props in the root project directory:
<PropertyGroup>
<DebugType>None</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
See more details at https://github.com/dotnet/core/issues/3689

Docker: Installed component of parent image disappear after run container

I want to make a docker image that contains an Asp.net core app and some other components. I have decided to pull the debian image, install the necessary components (in this case is the asterisk system), then commit and push it as my own image, let's call it A.
In the Asp.net core app, I use A as a parent component in dockefile and build a image, let's call it B.
But when I run B as a container, I can not find the components I already installed in the image A.
This is my dockerfile:
FROM vocaoson7/asterisk:king
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.sln .
COPY aspnetapp/*.csproj ./aspnetapp/
RUN dotnet restore
# copy everything else and build app
COPY aspnetapp/. ./aspnetapp/
WORKDIR /app/aspnetapp
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
WORKDIR /app
COPY --from=build /app/aspnetapp/out ./
ENTRYPOINT ["dotnet", "aspnetapp.dll"]
You are trying to use a multi-stage build and the way it works is that your final image is defined by your last FROM command in your Dockerfile and whatever follows that.
So for your case, all you will find in your final image is the aspnet:3.1 installation (from the base image used for the runtime stage) and an /app folder containing with what your build step generated in the out directory.
Your very first FROM has no influence whatsoever on the final image.

Where are NuGet libraries in Docker containers?

I'm building an ASP .NET Core 2.1 MVC application and I need to know where the NuGet libraries get stored, because one of them depends on a file I need to copy in the NuGet library folder. From the Dockerfile made by Visual Studio I see that it's making several images for each step of the building process, but Im so confused as to where the NuGet files are on the container's file system. I can't find it using find -iname "nuget" either.
per request my Dockerfile:
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 53204
EXPOSE 44391
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY ["Versandformulartool/Versandformulartool.csproj", "Versandformulartool/"]
RUN dotnet restore "Versandformulartool/Versandformulartool.csproj"
COPY . .
WORKDIR "/src/Versandformulartool"
RUN dotnet build "Versandformulartool.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "Versandformulartool.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Versandformulartool.dll"]

COPY . . command in Dockerfile for ASP.NET

The Visual Studio tooling for Docker creates a Dockerfile for ASP.NET projects containing a COPY . . command as below:
WORKDIR /src
COPY *.sln ./
...
COPY . .
From what I've read, the <src> parameter is relative to the context, so isn't affected by the WORKDIR /src command. The <dest> however is relative to the WORKDIR so will be pointing at /src.
Is this command just bringing over the remaining files from the root for packaging (docker-compose.yml, .dockerignore, etc.)? If so, then why is this done ahead of the RUN dotnet build... command?
Full Dockerfile below:
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY *.sln ./
COPY MyProject/MyProject.csproj MyProject/
RUN dotnet restore
COPY . . # The line mentioned above
WORKDIR /src/MyProject
RUN dotnet build -c Release -o /app
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "MyProject.dll"]
The COPY . . copies the entire project, recursively into the container for the build.
The reason for the separation of the first 2 COPY commands with dotnet restore and then the complete COPY . . with dotnet build is a Docker caching trick to speed up container image builds. It is done this way so the project dependencies don't need to be reinstalled every time a code change is made.
Docker images are built in layers. Docker compares the contents and instructions that would make up the each new layer to previous builds. If they match the SHA256 checksum for the existing layer, the build step for that layer can be skipped.
Code changes a lot more than dependencies, and dependencies are usually fetched from a slow(ish) network now. If you copy the code after the dependency installs are completed then you don't bust the cached dependency layer for every other change.
This is a common theme across many languages with a dependency manager. Go, Python, Node.js etc. The Node.js equivalent does the package.json and package-lock.json before the rest of the application contents:
WORKDIR /app
COPY package.json package-lock.json /app/
RUN npm install
COPY . /app/
CMD ["node", "app/index.js"]
Some more pointers on the above from Scott Hanselman: https://www.hanselman.com/blog/OptimizingASPNETCoreDockerImageSizes.aspx
PRO TIP: Docker is smart about making intermediate images and doing the least work, but it's useful if we (the authors) do the right thing as well to help it out.
For example, see where we COPY the .csproj over and then do a "dotnet restore"? Often you'll see folks do a "COPY . ." and then do a restore. That doesn't allow Docker to detect what's changed and you'll end up paying for the restore on EVERY BUILD.
By making this two steps - copy the project, restore, copy the code, this means your "dotnet restore" intermediate step will be cached by Docker and things will be WAY faster.
The first dot is “where i am now”
So it will copy everything from the same place as the dockerfile, to “where i am now” in the container.
The “where i am now” in the image/container is defined by https://docs.docker.com/engine/reference/builder/#workdir 433
So if you set:
WORKDIR /tmp
and do
COPY . .
It will copy everything from the current folder, to /tmp

Resources