-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
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:
curlgitwget
Related Issues
- Upcoming breaking change: Drop reference to buildpack-deps for SDK images [Original Announcement]
- Change the base image of the Windows and Alpine SDK images to maximize layer sharing
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%)