This repository has been archived by the owner. It is now read-only.

.NET Core Alpine Docker Image Ready for Testing #500

Closed
richlander opened this Issue Nov 21, 2017 · 16 comments

Comments

Projects
None yet
@richlander
Member

richlander commented Nov 21, 2017

.NET Core Alpine Docker Image Ready for Testing

An Alpine-based Docker image is now available for .NET Core. Alpine is much smaller than Debian, which we have used for the .NET Core base image to date. There have been many requests for an Alpine image. We are pleased to make it available. Please check out .NET Core Docker Alpine Production Sample (Preview) to see examples of using this image.

We have added two new images:

  • 2.1-runtime-alpine
  • 2.1-runtime-deps-alpine

Alpine support is part of the .NET Core 2.1 release. .NET Core 2.1 images are currently provided at the microsoft/dotnet-nightly repo, including the new Alpine images. .NET Core 2.1 images will be promoted to the microsoft/dotnet repo when .NET Core 2.1 is shipped as a Preview, expected to be early 2018.

Details

The primary goal of Alpine is very small deployments. We have been considering various design decisions to make .NET Core Alpine base images as small as possible to align with that. In this first iteration, we enabled .NET Core 2.0 Globalization Invariant Mode in order to reduce the default size of the image. This change reduced the image by ~30MB. You can see the reduction in size for .NET Core images relative to Debian in the following table.

2.1 Image Debian Alpine
-deps 153MB (68MB compressed) 13.8 MB (6MB compressed)
-runtime 222MB (96MB compressed) 82.5 (34MB compressed)

Note: The compressed size is what you will see in a registry and is the wire-size cost.

We are also considering saving more space by native-compiling fewer assemblies. .NET Core runtime assemblies are native-compiled with the crossgen tool in the Ready2Run format. Native-compiled code delivers superior startup performance but at the cost of 2-3x larger files. We have the opportunity to compile less, skipping compiling assemblies in part or in whole. We believe that we can save at least another 10MB through compiling less without a material drop in performance. For scenarios that value size over startup or where wire cost is significant, it may be valuable to aggressively reduce the number/% of compilation.

Alpine images are only available for .NET Core 2.1. At the current time, only Runtime images are available. We intend to offer SDK images at a later date.

Use cases that cannot tolerate Globalization invariant mode can reset the DOTNET_SYSTEM_GLOBALIZATION_INVARIANT environment variable and install the ICU package. Please check out .NET Core Docker Alpine Production Sample (Preview) to see examples of using this image with and without Globalization Invariant Mode enabled.

Call to Action

Please test your workloads with the new Alpine image. In particular, we want to know if enabling .NET Core Globalization Invariant Mode is acceptable/appreciated.

@khellang

This comment has been minimized.

Show comment
Hide comment
@khellang

khellang Nov 21, 2017

What's the difference between runtime and runtime-deps and when would you use each? I don't think this comes through in the post...

khellang commented Nov 21, 2017

What's the difference between runtime and runtime-deps and when would you use each? I don't think this comes through in the post...

@MichaelSimons

This comment has been minimized.

Show comment
Hide comment
@MichaelSimons

MichaelSimons Nov 21, 2017

Collaborator

@khellang - The runtime image contains the .NET Core runtime and is intended to run Framework-Dependent Deployed applications - see sample

The runtime-deps image contains just the native dependencies needed by .NET Core and is intended to run Self-Contained Deployed applications - see sample

Collaborator

MichaelSimons commented Nov 21, 2017

@khellang - The runtime image contains the .NET Core runtime and is intended to run Framework-Dependent Deployed applications - see sample

The runtime-deps image contains just the native dependencies needed by .NET Core and is intended to run Self-Contained Deployed applications - see sample

@richlander

This comment has been minimized.

Show comment
Hide comment
@richlander

richlander Nov 21, 2017

Member

JFYI: The split isn't new for Alpine. It's the same split we've had for Debian.

Member

richlander commented Nov 21, 2017

JFYI: The split isn't new for Alpine. It's the same split we've had for Debian.

@khellang

This comment has been minimized.

Show comment
Hide comment
@khellang

khellang Nov 21, 2017

Right. That's was my suspicion, but hadn't seen the split before stumbling across this post and figured someone else might wonder the same. Thanks! 😄

khellang commented Nov 21, 2017

Right. That's was my suspicion, but hadn't seen the split before stumbling across this post and figured someone else might wonder the same. Thanks! 😄

@richlander richlander changed the title from .NET Core Alpine Image Ready for Testing to .NET Core Alpine Docker Image Ready for Testing Nov 22, 2017

@shanselman

This comment has been minimized.

Show comment
Hide comment
@shanselman

shanselman Nov 22, 2017

Shouldn't it be microsoft/dotnet:2.1.x-runtime-alpine, given the current stuff is 2.0.0?

shanselman commented Nov 22, 2017

Shouldn't it be microsoft/dotnet:2.1.x-runtime-alpine, given the current stuff is 2.0.0?

@richlander

This comment has been minimized.

Show comment
Hide comment
@richlander

richlander Nov 22, 2017

Member

We are pushing the exact same form/scheme of tags as always. See @ https://hub.docker.com/r/microsoft/dotnet-nightly/

For the most part, we offer four types of tags:

  • Specific digest (this isn't actually a tag)
  • Specific patch
  • Specific major/minor (roll-forward on patch)
  • Roll-forward (multiple variants of this one)

We believe that most scenarios are best served by referencing a specific digest or a specific major/minor, as is used in the example that you are referencing. The specific patch tags can be useful, for sure, but you have to realize that the OS is being patched underneath you. So, the scenario for the specific patch is that you want to opt-in to .NET Core patch updates but you are fine with automatic OS updates. And by "automatic", I mean automatic in environments that docker pull, either by your explicit action or on your behalf.

For samples, the specific major/minor tags is really the only option available to us. We don't want to update samples for each .NET Core patch update and we certainly don't want people pulling older (less secure) patches in the case we get lazy and don't update those samples.

We may choose to stop publishing the specific patch tags for .NET Core 3.0 (meaning not for .NET Core 2.x).

Member

richlander commented Nov 22, 2017

We are pushing the exact same form/scheme of tags as always. See @ https://hub.docker.com/r/microsoft/dotnet-nightly/

For the most part, we offer four types of tags:

  • Specific digest (this isn't actually a tag)
  • Specific patch
  • Specific major/minor (roll-forward on patch)
  • Roll-forward (multiple variants of this one)

We believe that most scenarios are best served by referencing a specific digest or a specific major/minor, as is used in the example that you are referencing. The specific patch tags can be useful, for sure, but you have to realize that the OS is being patched underneath you. So, the scenario for the specific patch is that you want to opt-in to .NET Core patch updates but you are fine with automatic OS updates. And by "automatic", I mean automatic in environments that docker pull, either by your explicit action or on your behalf.

For samples, the specific major/minor tags is really the only option available to us. We don't want to update samples for each .NET Core patch update and we certainly don't want people pulling older (less secure) patches in the case we get lazy and don't update those samples.

We may choose to stop publishing the specific patch tags for .NET Core 3.0 (meaning not for .NET Core 2.x).

@cburman01

This comment has been minimized.

Show comment
Hide comment
@cburman01

cburman01 Dec 6, 2017

Will the -runtime image work for aspnet core applications? I was able to build from the image fine but am getting this when running the container:

Error:
  An assembly specified in the application dependencies manifest (WebApplication7.deps.json) was not found:
    package: 'Microsoft.ApplicationInsights.AspNetCore', version: '2.1.1'
    path: 'lib/netstandard1.6/Microsoft.ApplicationInsights.AspNetCore.dll'
  This assembly was expected to be in the local runtime store as the application was published using the following target manifest files:
    aspnetcore-store-2.0.0-linux-x64.xml;aspnetcore-store-2.0.0-osx-x64.xml;aspnetcore-store-2.0.0-win7-x64.xml;aspnetcore-store-2.0.0-win7-x86.xml

Docker file:

FROM microsoft/dotnet:2.0-sdk as builder

RUN mkdir -p /root/src/app/WebApplication7
WORKDIR /root/src/app/WebApplication7

COPY . .
RUN dotnet restore ./WebApplication7.csproj

COPY . .
RUN dotnet publish -c release -o published

FROM microsoft/dotnet-nightly:2.1-runtime-alpine


WORKDIR /root/
COPY --from=builder /root/src/app/WebApplication7/published .
ENV ASPNETCORE_URLS=http://+:5000
EXPOSE 5000/tcp
CMD ["dotnet", "./WebApplication7.dll"]

The application is just a barebones aspnet core application template from visual studio.

cburman01 commented Dec 6, 2017

Will the -runtime image work for aspnet core applications? I was able to build from the image fine but am getting this when running the container:

Error:
  An assembly specified in the application dependencies manifest (WebApplication7.deps.json) was not found:
    package: 'Microsoft.ApplicationInsights.AspNetCore', version: '2.1.1'
    path: 'lib/netstandard1.6/Microsoft.ApplicationInsights.AspNetCore.dll'
  This assembly was expected to be in the local runtime store as the application was published using the following target manifest files:
    aspnetcore-store-2.0.0-linux-x64.xml;aspnetcore-store-2.0.0-osx-x64.xml;aspnetcore-store-2.0.0-win7-x64.xml;aspnetcore-store-2.0.0-win7-x86.xml

Docker file:

FROM microsoft/dotnet:2.0-sdk as builder

RUN mkdir -p /root/src/app/WebApplication7
WORKDIR /root/src/app/WebApplication7

COPY . .
RUN dotnet restore ./WebApplication7.csproj

COPY . .
RUN dotnet publish -c release -o published

FROM microsoft/dotnet-nightly:2.1-runtime-alpine


WORKDIR /root/
COPY --from=builder /root/src/app/WebApplication7/published .
ENV ASPNETCORE_URLS=http://+:5000
EXPOSE 5000/tcp
CMD ["dotnet", "./WebApplication7.dll"]

The application is just a barebones aspnet core application template from visual studio.

@NileshGule

This comment has been minimized.

Show comment
Hide comment
@NileshGule

NileshGule Dec 9, 2017

The current image is exposing 5000 as the default port. We need to explicitly expose 80 or 8080 or any other custom port using the UseUrls method. The Microsoft/aspnetcore:2.0 image was able to map the ports exposed in Dockerfile without explicitly specifying the ports in BuildWebHost method. I tried upgrading to Alpine based image recently and had to make changes to expose specific ports (http://www.handsonarchitect.com/2017/12/migrate-dotnet-core-docker-image-to.html)

Will the stable version of Alpine based image support this feature of mapping ports from Dockerfile?

NileshGule commented Dec 9, 2017

The current image is exposing 5000 as the default port. We need to explicitly expose 80 or 8080 or any other custom port using the UseUrls method. The Microsoft/aspnetcore:2.0 image was able to map the ports exposed in Dockerfile without explicitly specifying the ports in BuildWebHost method. I tried upgrading to Alpine based image recently and had to make changes to expose specific ports (http://www.handsonarchitect.com/2017/12/migrate-dotnet-core-docker-image-to.html)

Will the stable version of Alpine based image support this feature of mapping ports from Dockerfile?

@kjbetz

This comment has been minimized.

Show comment
Hide comment
@kjbetz

kjbetz Dec 13, 2017

@cburman01 You're building / compiling your app with 2.0 and then trying to run with 2.1. You'll probably need to change your first line to something like this: FROM microsoft/dotnet-nightly:2.1-sdk as builder

https://hub.docker.com/r/microsoft/dotnet-nightly/

kjbetz commented Dec 13, 2017

@cburman01 You're building / compiling your app with 2.0 and then trying to run with 2.1. You'll probably need to change your first line to something like this: FROM microsoft/dotnet-nightly:2.1-sdk as builder

https://hub.docker.com/r/microsoft/dotnet-nightly/

@ChaosEngine

This comment has been minimized.

Show comment
Hide comment
@ChaosEngine

ChaosEngine Dec 26, 2017

I am getting segmentation fault when building with dotnet-nightly:2.1-sdk and running under 2.1-runtime-alpine.
Just by using plain dotnet new mvc && dotnet publish && dotnet app.dll.
If needed, I could prepare full repro info dump.

ChaosEngine commented Dec 26, 2017

I am getting segmentation fault when building with dotnet-nightly:2.1-sdk and running under 2.1-runtime-alpine.
Just by using plain dotnet new mvc && dotnet publish && dotnet app.dll.
If needed, I could prepare full repro info dump.

@steve-todorov

This comment has been minimized.

Show comment
Hide comment
@steve-todorov

steve-todorov Feb 1, 2018

Are there any plans for an Alpine sdk version as well?

steve-todorov commented Feb 1, 2018

Are there any plans for an Alpine sdk version as well?

@MichaelSimons

This comment has been minimized.

Show comment
Hide comment
@MichaelSimons

MichaelSimons Feb 1, 2018

Collaborator

@steve-todorov - yes there is. There is an active PR - #508. It is currently blocked on a product issue.

Collaborator

MichaelSimons commented Feb 1, 2018

@steve-todorov - yes there is. There is an active PR - #508. It is currently blocked on a product issue.

@steve-todorov

This comment has been minimized.

Show comment
Hide comment
@steve-todorov

steve-todorov Feb 2, 2018

@MichaelSimons thanks for your reply! I'll be keeping an eye at #508 in that case.

steve-todorov commented Feb 2, 2018

@MichaelSimons thanks for your reply! I'll be keeping an eye at #508 in that case.

@ChristianRMKoerber

This comment has been minimized.

Show comment
Hide comment
@ChristianRMKoerber

ChristianRMKoerber Feb 6, 2018

@cburman01 @kjbetz
I am getting exactly the same error regardless of whether I am using dotnet-nightly:2.1-sdk or microsoft/dotnet:2.0-sdk.

ChristianRMKoerber commented Feb 6, 2018

@cburman01 @kjbetz
I am getting exactly the same error regardless of whether I am using dotnet-nightly:2.1-sdk or microsoft/dotnet:2.0-sdk.

@isberg

This comment has been minimized.

Show comment
Hide comment
@isberg

isberg Feb 9, 2018

In the hope someone will save alot of time and frustration, I am sharing my minimal solution to creating, publishing and running a web project.

The issues that I have found and handled is:

  • switched package Microsoft.AspNetCore.App to Microsoft.AspNetCore.App
  • installed missing libuv.so in alpine
  • set ASPNETCORE_URLS
FROM microsoft/dotnet-nightly:2.1-sdk AS builder

WORKDIR /src
RUN dotnet new web \
 && sed -i 's/Microsoft.AspNetCore.App/Microsoft.AspNetCore/g' *.csproj \
 && dotnet publish -c Release -o /app


FROM microsoft/dotnet-nightly:2.1-runtime-alpine AS runtime
RUN apk add --no-cache libuv \
 && ln -s /usr/lib/libuv.so.1 /usr/lib/libuv.so
ENV ASPNETCORE_URLS http://+:80

WORKDIR /app
COPY --from=builder /app .
ENTRYPOINT ["dotnet", "src.dll"]

dotnet new mvc? I failed horribly there. Have not tried with a custom made .csproj file or as a self-contained application though.

isberg commented Feb 9, 2018

In the hope someone will save alot of time and frustration, I am sharing my minimal solution to creating, publishing and running a web project.

The issues that I have found and handled is:

  • switched package Microsoft.AspNetCore.App to Microsoft.AspNetCore.App
  • installed missing libuv.so in alpine
  • set ASPNETCORE_URLS
FROM microsoft/dotnet-nightly:2.1-sdk AS builder

WORKDIR /src
RUN dotnet new web \
 && sed -i 's/Microsoft.AspNetCore.App/Microsoft.AspNetCore/g' *.csproj \
 && dotnet publish -c Release -o /app


FROM microsoft/dotnet-nightly:2.1-runtime-alpine AS runtime
RUN apk add --no-cache libuv \
 && ln -s /usr/lib/libuv.so.1 /usr/lib/libuv.so
ENV ASPNETCORE_URLS http://+:80

WORKDIR /app
COPY --from=builder /app .
ENTRYPOINT ["dotnet", "src.dll"]

dotnet new mvc? I failed horribly there. Have not tried with a custom made .csproj file or as a self-contained application though.

@MichaelSimons

This comment has been minimized.

Show comment
Hide comment
@MichaelSimons
Collaborator

MichaelSimons commented Feb 15, 2018

Issue moved to dotnet/dotnet-docker #371 via ZenHub

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.