dotnet-docker
dotnet-docker copied to clipboard
Provide an official ASP.NET alpine-extra image with globalization support (ICU and tzdata)
Please reconsider providing an official alpine-extra image for ASP.NET (and runtime) that supports globalization.
We don't plan to offer runtime and aspnet images based on 8.0-jammy-chiseled-extra. We will re-consider that if there is sufficient demand.
Currently, we are either forced to:
- Use a custom alpine base image that adds globalization data as documented by dotnet here. Or:
- Use a debian image (bookworm-slim), which is ~74MB bigger than the custom alpine image with globalization data 👎
This goes against the "Batteries included and Choose your own adventure" themes in the announcement. We would like to concentrate on developing apps, not maintaining custom containers.
Thank you.
EDIT: For anyone looking to get the smallest image in the meantime, you can use the the runtime-deps:8.0-alpine-extra
image like this:
dotnet publish --os linux-musl --self-contained true -p:ContainerBaseImage=mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine-extra -p:PublishProfile=DefaultContainer
@DanielLaberge - based on the referenced issue at https://github.com/dotnet/sdk-container-builds/issues/512, I'm assuming this is in the context of wanting to use the SDK container publishing feature and that you don't want to have to maintain your own Dockerfile. Is that correct?
@mthalman That is correct. I will edit the issue to reflect that.
You could use self-contained deployment with the runtime-deps:8.0-alpine-extra
image with SDK OCI publishing. Can you share why that isn't satisfactory?
This goes against the "Batteries included and Choose your own adventure" themes in the announcement.
I'm glad that folks read our announcements!
@richlander I will gladly try this and report my results if someone could point me to relevant documentation on how to achieve this with an ASP.NET app.
I've tried adding the following to my .csproj: <ContainerBaseImage>mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine-extra</ContainerBaseImage>
Then building with dotnet publish --os linux --arch x64 --self-contained true -p:PublishProfile=DefaultContainer -c Release
But running the container produces this error: exec /app/MyAppName: no such file or directory
I assume I must be missing some step, but I couldn't find relevant documentation or examples.
Could you try adding the argument --self-contained true
to your publish command, or adding <SelfContained>true</SelfContained>
property to your csproj?
Also adding @baronfel.
@lbussell I indeed had the <SelfContained>true</SelfContained>
property in my .csproj but forgot to mention it in my last comment. I'll edit it to avoid further confusion.
I have reproduced the same error with a blank ASP.NET template like so:
mkdir aspnet-alpine-extra-test && cd aspnet-alpine-extra-test
dotnet new webapp
dotnet publish --os linux --arch x64 --self-contained true -p:ContainerBaseImage=mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine-extra -p:PublishProfile=DefaultContainer -c Release
docker run aspnet-alpine-extra-test:latest
exec /app/aspnet-alpine-extra-test: no such file or directory
However, if I don't specify the ContainerBaseImage, it defaults to mcr.microsoft.com/dotnet/runtime-deps:8.0.0-rc.2
(based on Debian 12 instead of runtime-deps:8.0-alpine-extra) and then runs successfully. Clearly there is something missing.
Switch to:
dotnet publish --os linux-musl
You are saying "I want an app compatible with Linux glibc" when you want one compatible with musl (what Alpine uses).
If you are building on x64, then you can skip --arch x64
. Also -c Release
can be skipped. That's now the default for dotnet publish
.
After we get this resolved, you can try trimming to try to make the image smaller, with -p:PublishTrimmed=true
.
We have not rejected the overall request. It makes sense to see if this works.
Specifying --os linux-musl
does indeed work. Thank you for that.
I wasn't aware of this detail, being unfamiliar with alpine images.
The error message produced when calling dotnet publish --self-contained -p:PublishProfile=DefaultContainer
without specifying --os
is misleading in that regard as it doesn't mention 'linux-musl'.
error MSB4018: Microsoft.NET.Build.Containers.BaseImageNotFoundException: The RuntimeIden
tifier 'win-x64' is not supported by dotnet/runtime-deps:8.0-alpine-extra.
The supported RuntimeIdentifiers are linux-x64,linux-arm,linux-arm64
I think this discussion illustrates why an official aspnet alpine-extra image might be helpful to the community; allowing everyone to benefit from the smallest possible image without this kind of friction and specific required knowledge. It would be as simple as setting -p:ContainerFamily=alpine-extra
.
Thank you for the consideration.
Can you file a bug on dotnet/sdk with your findings on supported RuntimeIdentifiers
. You are correct with your interpretation. Only linux-musl
variants should be offered there.
Part of the reason that Alpine images are smaller is because they use a different libc variant called musl. That makes Alpine incompatible with software compiled for Ubuntu, for example. This is a generic problem. For example Project Portola was established to create a Java port for Alpine. We didn't make such a big deal of doing the work, but it wasn't cheap.
This complexity leaks out to users. This is what RIDs are for. We've tried to hide that with this -a
and --os
arguments. Still, you need to know how linux
and linux-musl
are different. This isn't needed in a Dockerfile if you use the Alpine SDK since dotnet publish
defaults to linux-musl
in that context. With SDK publish run on your dev machine (likely not Alpine), then you need to address this inherent targeting complexity.
I hope that explanation helps.
[Triage] @DanielLaberge, it seems like your problem is resolved, right?
We will leave this issue open in order to collect feedback on whether there is more demand for runtime-
and aspnet-extra
images.
@lbussell: Yes, thank you.
Globalization and the icu support are pretty important features.
--self-contained
is working with runtime-deps:8.0-jammy-chiseled-extra
but it would introduce around 100MB for every single build and application. If there was an aspnet:8.0-jammy-chiseled-extra
we could use --no-self-containted
.
Having a small image might be important but safe by default and making it simple to do the right thing is even more important. No root user and no shell are awesome features in that regards.
I would definitely appreciate this change, we are currently using dotnet publish in combination with ContainerFamily to build the containers.
at the moment we have to use -p:ContainerFamily=jammy-chiseled-extra but if there is an equivalent -p:ContainerFamily=alpine-extra that would be great.
@baronfel
@richlander
Can you please clarify few question? I am using dotnet cli 8.0.203
I have created webapi app using cli and added following in .csproj file
<ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:8.0.3-jammy-chiseled-extra</ContainerBaseImage>
published & run using following commands.
dotnet publish -t:PublishContainer
docker run --rm -d -p 8000:8080 webapidemo
I am able to access the API.
I want to try the same with Alpine, so I followed this issue. Command I have used is this
dotnet publish -t:PublishContainer --os linux-musl \
--self-contained -p:PublishTrimmed=true \
-p:ContainerBaseImage=mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine-extra
When I try to run the container using above command and access the API it returns 500 error.
Doesn't above command include dotnet runtime & aspnet in the image? I thought --self-contained
does that.
How should I resolve this?
Also, is there a way to output dockerfile generated by publish command?
We would greatly benefit from having aspnet
alpine-extra
images at my company. Right now, we have many of our services running on the base alpine
image but, as Entity Framework Core needs ICU to work, we have to install ICU manually with Dockerfiles. Having more options is never bad, and support for Entity Framework Core on aspnet
Alpine would be appreciated by lots of developers.