Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Breaking Change: Removal of buildpack-deps in 5.0 SDK Docker images #2376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mthalman opened this issue Nov 10, 2020 · 0 comments
Closed

Breaking Change: Removal of buildpack-deps in 5.0 SDK Docker images #2376

mthalman opened this issue Nov 10, 2020 · 0 comments

Comments

@mthalman
Copy link
Member

Removal of buildpack-deps from 5.0 SDK Docker images

Starting with .NET 5.0, SDK Docker images will no longer have buildpack-deps as a parent image for Debian and Ubuntu. This breaking change was made as part of a larger effort to enable more layer sharing amongst the set of Docker images. It also helps to reduce the security vulnerability surface area by virtue of simply having less software installed in these images.

Details

As mentioned above, this change was part of a larger effort to maximize layer sharing, resulting in more efficient transfers of images. This change was also applied to the Alpine and Nano Server SDK images. Alpine was previously based on runtime-deps and Nano Server was previously based on the base nanoserver image. These images are all now based on aspnet.

Image Original parent image New parent image
sdk:5.0-buster buildpack-deps:buster-scm aspnet:5.0-buster-slim
sdk:5.0-focal buildpack-deps:focal-scm aspnet:5.0-focal
sdk:5.0-alpine runtime-deps:5.0 aspnet:5.0-alpine
sdk:5.0-nanoserver nanoserver aspnet:5.0-nanoserver

To compensate for the loss of buildpack-deps for Debian and Ubuntu, the following list of packages have been added to those SDK images:

  • curl
  • git
  • wget

Related Issues

Breaks and Workarounds

If you rely on tools provided by buildpack-deps:scm (beyond the three mentioned above), you will be broken by this change when transitioning to .NET 5.0.

The complete list of tools provided by buildpack-deps:scm can be easily discovered by looking at the following Dockerfiles, for the curl and scm layers.

For Debian:

For Ubuntu:

If you rely on these tools as part of docker build, you are encouraged to install the required tool(s) yourself in your Dockerfile, or rely on multi-stage build, by using a buildpack-deps stage, as we do for .NET runtime images.

If you rely on these tools as part of docker run, you can potentially install them via a script.

Context

Since .NET Core 1.0, we've been releasing SDK images on top of buildpack-deps images. We made this choice for two reasons:

  • We needed access to curl to download .NET Core.
  • We saw that other developer platforms (for their SDK) depend on buildpacks-deps:scm (example), which contains curl.

This made choosing buildpacks-deps:scm for the .NET Core SDK images an easy choice. We did that and moved on.

Later, Docker developed the multi-stage-build feature, which opened up many new possibilities. In particular, this feature enables you to download or build assets in one stage, and then copy into another. That's a pattern we've adopted for our runtime images.

We realized early on that the buildpack-deps dependency was problematic because it meant that the SDK images could not depend on runtime images. This means for multi-stage builds that you download the runtime twice, once with the SDK and another time for the final image. That's very unfortunate.

Both Windows and Alpine don't have a buildpack-deps image offered. That means that we had more freedom on how to layer those images.

Upon further thought, we realized that we didn't have any actual customer evidence that buildpack-deps was needed (as part of sdk images). We have plenty of evidence that the layer is problematic, and can deliver a sizable performance improvement to anyone using the sdk and a runtime or aspnet image in a workflow (multi-stage build of a .NET image would be the most obvious example). We believe that this change will have a large positive impact on millions of builds ever day, and have a massive impact on any commercial build host.

We hope that we can deliver this benefit to .NET docker image users. In particular, we hope that we can find satisfactory workarounds for users that are impacted by this change.

Size Impact

Here's a comparison of the benefits these changes provide in terms of the download cost savings. The canonical scenarios here are a multi-stage Dockerfile that builds and publishes either an ASP.NET app (see the sample ASP.NET Core Dockerfile) or .NET Console app (see the sample .NET Dockerfile). The scenario involves first pulling the sdk image in order to build the application and then pulling the aspnet or runtime image to contain the published application. Before these changes, there was no layer sharing between the runtime-based images (aspnet and runtime) and the sdk image. This was wasteful because the SDK image does contain both ASP.NET Core and runtime bits; it just wasn't based on either of those images. With the changes that were made here, sdk is now based on the aspnet image which means that once you've pulled sdk, you also now have the aspnet and runtime layers. This provides substantial download savings when both images need to be pulled.

Ubuntu 20.04 (Focal)

ASP.NET App

.NET Core 3.1 .NET 5.0 Size Difference
1. Pull sdk image 240 MB 223 MB -17 MB (-7%)
2. Pull aspnet image 85 MB 5 KB (manifest only) -85 MB (-100%)

Net download savings: 102 MB (-31%)

Console App

.NET Core 3.1 .NET 5.0 Size Difference
1. Pull sdk image 240 MB 223 MB -17 MB (-7%)
2. Pull runtime image 30 MB 5 KB (manifest only) -30 MB (-100%)

Net download savings: 47 MB (-17%)

Debian 10 (Buster)

ASP.NET App

.NET Core 3.1 .NET 5.0 Size Difference
1. Pull sdk image 258 MB 214 MB -44 MB (-17%)
2. Pull aspnet image 80 MB 4 KB (manifest only) -80 MB (-100%)

Net download savings: 124 MB (-37%)

Console App

Before After Size Difference
1. Pull sdk image 258 MB 214 MB -44 MB (-17%)
2. Pull runtime image 73 MB 3 KB (manifest only) -73 MB (-100%)

Net download savings: 117 MB (-35%)

@mthalman mthalman pinned this issue Nov 10, 2020
@mthalman mthalman unpinned this issue Nov 10, 2020
@mthalman mthalman pinned this issue Nov 10, 2020
@mthalman mthalman unpinned this issue Nov 10, 2020
elafarge added a commit to elafarge/dotnet-docker that referenced this issue Nov 18, 2020
This package is now required for "dotnet watch" to actually watch for
file changes on Debian based images.

NOTE: with this patch we're installing the package on Ubuntu
based-distributions as well, as a (undesired?) side-effect.

The alternative would be to use Cottle templating language to only add
this patch for debian-based images.
The problem is their name varies accross versions (buster, bullseye...)
this would have made this bugfix less change-resistant.

Caused by: dotnet#2376

Github issue: dotnet#2396
elafarge added a commit to elafarge/dotnet-docker that referenced this issue Nov 18, 2020
This package is now required for "dotnet watch" to actually watch for
file changes on Debian based images.

NOTE: with this patch we're installing the package on Ubuntu
based-distributions as well, as a (undesired?) side-effect.

The alternative would be to use Cottle templating language to only add
this patch for debian-based images.
The problem is their name varies accross versions (buster, bullseye...)
this would have made this bugfix less change-resistant.

Caused by: dotnet#2376

Github issue: dotnet#2396
@dotnet dotnet locked and limited conversation to collaborators Apr 13, 2022
@mthalman mthalman converted this issue into discussion #3675 Apr 13, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests

3 participants
@MichaelSimons @mthalman and others