1

A couple of months ago, I created my first Dockerfile for a console application. This console application depends on several other c# projects, so it is a bit more complex than the standard samples that you'd typically find on the internet. The Dockerfile "works", i.e. I can create an image and run a container. However, I know that it contains several flaws, and now is the time to improve this Dockerfile. The current version is

FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src

COPY Directory.Build.props .
COPY src/ .

RUN dotnet restore "MyProject/MyProject.csproj"
COPY . .
WORKDIR "/src/MyProject"
RUN dotnet build "MyProject.csproj" -c Release -o /app/build --no-restore

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 .
ENTRYPOINT ["dotnet", "MyProject.dll"]

Clearly, the multiple copying of files needs to be addressed, but first I want to reduce the image size by using the Alpine image. Based on the sample in Microsoft samples, I've come up with

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/runtime:6.0-alpine-amd64 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /src

COPY Directory.Build.props .
COPY src/ .

RUN dotnet restore "MyProject/MyProject.csproj" -r linux-musl-x64
COPY . .
WORKDIR "/src/MyProject"
RUN dotnet build "MyProject.csproj" -c Release -o /app/build --no-restore

FROM build AS publish
RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish -r linux-musl-x64 --self-contained false --no-restore

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["./MyProject"]

Using the modified Dockerfile, I can build a container, but it will not start. There are also no logs. Following the approach of exporting and extracting the container, I see that the folder "app" the same amount of files as in the original version, except the original version has an additional folder "runtimes". So what is wrong with the modified version? Are there any suggestions to bring down the size of the image?

(PS, I've updated the question to include suggested fix.)

SimonAx
  • 1,176
  • 1
  • 8
  • 32
  • Can you launch command `bash` and check outputs of `dotnet MyProject.dll` and `ls`? – efkah Sep 09 '22 at 17:03
  • @efkah Excellent suggestion, I tried ` docker run --rm -it --entrypoint /bin/sh ` (it does not contain bash) and subsequently `ls`. The file that I want to launch (MyProject) is there. If I do `./MyProject` I get "Segementation fault". – SimonAx Sep 09 '22 at 19:12
  • If I replace the runtime:6.0-alpine-amd64 by runtime:6.0-bullseye-slim-amd64 (and use different arguments to `dotnet restore` and `dotnet publish`, I get a container that works. Seems that whatever I'm trying to do in Alpine is hitting a snag. – SimonAx Sep 09 '22 at 19:16

2 Answers2

0

I'm pretty sure the issue is with this line:

RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish --no-restore

You didn't include the linux-musl-x64 RID here like you did in the dotnet restore command.

You should change it to this:

RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish -r linux-musl-x64 --self-contained false --no-restore

This is illustrated in the .NET samples at https://github.com/dotnet/dotnet-docker/blob/90ada36795a870fb0113de7406a683ed05a2057f/samples/dotnetapp/Dockerfile.alpine-x64#L11:

RUN dotnet publish -c Release -o /app -r linux-musl-x64 --self-contained false --no-restore
Matt Thalman
  • 3,540
  • 17
  • 26
  • Thanks for the hint, but unfortunately it did not help. I've updated the original question to include your suggestin. – SimonAx Sep 09 '22 at 15:26
0

I had the same issue trying to run a Background Service using dotnet MyProject.dll.

So What I did was to change de docker image FROM mcr.microsoft.com/dotnet/runtime to FROM mcr.microsoft.com/dotnet/aspnet

And on the publish step I changed to use UseAppHost=false:

RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish -p:UseAppHost=false

The complete docker file based on yours:

FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine-amd64 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:6.0-alpine AS build
WORKDIR /src

COPY Directory.Build.props .
COPY src/ .

RUN dotnet restore "MyProject/MyProject.csproj" 
COPY . .
WORKDIR "/src/MyProject"
RUN dotnet build "MyProject.csproj" -c Release -o /app/build --no-restore

FROM build AS publish
RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish -p:UseAppHost=false --no-restore

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyProject.dll"]
Bruno Matuk
  • 562
  • 5
  • 11