-
Notifications
You must be signed in to change notification settings - Fork 288
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
Layer compression/flattening #1595
Comments
One thought that comes up. We are talking about a balancing thing, don't we. On the one hand side, small individual layers support commonly used buildpacks to be packaged without duplication. On the other hand side, they increase the layers and 127 is a hard and pretty low limit. If |
In practice, this doesn't always happen though. At least in Paketo, what happens is that we see slightly different versions of component buildpacks used by different composite buildpacks which cannot be deduplicated. I get what you're saying though. I don't think this should be the default behavior, but I do think pack should support a flag that can enable this behavior. |
I think @ForestEckhardt mentioned this in WG at some point last year. Is it something like |
Yes, basically. A builder is made up of a base build image plus layers and layers of buildpacks on top of that. If you add enough buildpacks, you'll eventually hit the layer limit. Ex: a paketo builder looks roughly like this
but since all of the buildpacks above are composite buildpacks, they get expanded and you end up with a much larger set of buildpacks and a much larger number of layers. Because of the way buildpacks are laid out, I think we can be reasonably sure that you won't have overlapping files across layers (i.e. across buildpacks), so what I'd like to see when Maybe compressing/flattening layers isn't the best way to describe it. Another way to look at it would be when pack builds the layers, just build fewer layers. Put all of the expanded buildpacks from a composite buildpack into one layer. Hope that helps to clarify. Thanks |
Hi @dmikusa! cc @matthewmcnew @natalieparellano (I copied you because we were discussing about this) I've being working on this, and I created a draft PR, could you take a look at the pull request description? I tried to show there the current behavior/output and I will like to double check that is what you had in mind. Another question, I am also working on adding a similar behavior to the command Here is an example of what is doing. Based on our current samples repository I created a meta-buildpack called samples/my-programming-lang which has the following buildpack.toml # Buildpack API version
api = "0.2"
# Buildpack ID and metadata
[buildpack]
id = "samples/my-programming-lang"
version = "0.0.1"
name = "My programming languages buildpacks"
homepage = "https://github.com/buildpacks/samples/tree/main/buildpacks/my-programming-lang"
# Order used for detection
[[order]]
[[order.group]]
id = "samples/java-maven"
version = "0.0.1"
[[order.group]]
id = "samples/kotlin-gradle"
version = "0.0.1"
[[order.group]]
id = "samples/ruby-bundler"
version = "0.0.1" I packaged this buildpack and save it into my docker daemon, as expected, it has 4 layers as we can see in this image: I now update the hello-universe meta-buildpack to include this new meta-buildpack, adding the following to the hello-universe/buildpack.toml # added
[[order.group]]
id = "samples/my-programming-lang"
version = "0.0.1" The [buildpack]
uri = "samples/buildpacks/hello-universe/"
[[dependencies]]
uri = "samples/buildpacks/hello-moon"
[[dependencies]]
uri = "docker://cnbs/sample-package:hello-world"
[[dependencies]]
uri = "docker://my-programming-package" After that, I package the pack buildpack package my-hello-universe-flatten.cnb --config ./package.toml --format file --flatten-layers Checking the labels in the Config file cat blobs/sha256/dc7dc9552d981001a660084d310a9435644fe5a6a3dad6f0ddaae733d5a685db | jq ' .config.Labels | ."io.buildpacks.buildpack.layers" | fromjson' I get the following: {
"samples/hello-moon": {
"0.0.1": {
"api": "0.2",
"stacks": [ ... ],
"layerDiffID": "sha256:0a29dd5e581a43de61913fc348606faf450c7ba1557f8c1d5a961cbb335bcc17",
"homepage": "https://github.com/buildpacks/samples/tree/main/buildpacks/hello-moon",
"name": "Hello Moon Buildpack"
}
},
"samples/hello-universe": {
"0.0.1": {
"api": "0.2",
"order": [...],
"layerDiffID": "sha256:a7752f36f04c03e6dda5a21741b1b12d8aa564556b317193d72b76286fe00464",
"homepage": "https://github.com/buildpacks/samples/tree/main/buildpacks/hello-universe",
"name": "Hello Universe Buildpack"
}
},
"samples/hello-world": {
"0.0.1": {
"api": "0.2",
"stacks": [...],
"layerDiffID": "sha256:18e9caa9f9836f546d7c5c0ed6ce0f87c99b3987b686eac40f244bb1e91db471",
"homepage": "https://github.com/buildpacks/samples/tree/main/buildpacks/hello-world",
"name": "Hello World Buildpack"
}
},
"samples/java-maven": {
"0.0.1": {
"api": "0.2",
"stacks": [...],
"layerDiffID": "sha256:32f20af929eda77a48ab04a2851c657d06c43a6e63106a2c536295d6c2e35479",
"homepage": "https://github.com/buildpacks/samples/tree/main/buildpacks/java-maven",
"name": "Sample Java Maven Buildpack"
}
},
"samples/kotlin-gradle": {
"0.0.1": {
"api": "0.2",
"stacks": [...],
"layerDiffID": "sha256:32f20af929eda77a48ab04a2851c657d06c43a6e63106a2c536295d6c2e35479",
"homepage": "https://github.com/buildpacks/samples/tree/main/buildpacks/kotlin-gradle",
"name": "Sample Kotlin Gradle Buildpack"
}
},
"samples/my-programming-lang": {
"0.0.1": {
"api": "0.2",
"order": [
{
"group": [
{
"id": "samples/java-maven",
"version": "0.0.1"
},
{
"id": "samples/kotlin-gradle",
"version": "0.0.1"
},
{
"id": "samples/ruby-bundler",
"version": "0.0.1"
}
]
}
],
"layerDiffID": "sha256:32f20af929eda77a48ab04a2851c657d06c43a6e63106a2c536295d6c2e35479",
"homepage": "https://github.com/buildpacks/samples/tree/main/buildpacks/my-programming-lang",
"name": "My programming languages buildpacks"
}
},
"samples/ruby-bundler": {
"0.0.1": {
"api": "0.2",
"stacks": [...],
"layerDiffID": "sha256:32f20af929eda77a48ab04a2851c657d06c43a6e63106a2c536295d6c2e35479",
"homepage": "https://github.com/buildpacks/samples/tree/main/buildpacks/ruby-bundler",
"name": "Sample Ruby Buildpack"
}
}
} I removed some data for simplicity, but we can see that all the layers for meta-buidpack my-programming-lang were flatten into one layer (sha256:32f20af929eda77a48ab04a2851c657d06c43a6e63106a2c536295d6c2e35479), and the reason for that, is because when we iterate over the dependencies in the package.toml file for hello-universe we found a meta-buildpack there and the flag enables the compression. The final manifest has 4 layers: {
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 4089,
"digest": "sha256:dc7dc9552d981001a660084d310a9435644fe5a6a3dad6f0ddaae733d5a685db"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 3748,
"digest": "sha256:77e05dd57bf427eb4f972075f514b9ffa26a8804a148d85b4675fe04252cbf52"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 541,
"digest": "sha256:48440a87a2e4637e5704e993f569a89ad6331289a13eb4cbb61ad125d94b8f8f"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 1051,
"digest": "sha256:d35cb095ab7fc25ca4bb0e61c3f802d7edb8505545464399f23ed98831a7556c"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 1143,
"digest": "sha256:df91948a4b0953fdac230b90cc3d7370eddb0e3f14a3b040a7402da22fa916b7"
}
]
}
I just want to validate this behavior is correct. Thanks |
Just thinking out loud here, Similar to how we have |
This is fantastic, thanks for working on this @jjbustamante! I will give things a try and let you know how it goes. |
Description
When you build more complicated buildpacks and then pull many of those together into a builder, you can quickly hit the layer limit for a container image.
Proposed solution
There are some seemingly natural points where pack could compress or flatten layers for the images it generates. For example, composite/meta buildpacks. When you are creating a builder or buildpack that consists of other composite/meta buildpacks pack could first flatten all of the layers from the composite buildpack and then create the new image with just a single layer for that composite/meta buildpack (this is opposed to the current behavior which inlines all of the layers from the composite/meta buildpack).
Describe alternatives you've considered
We might be able to hack this together with something like the following but I haven't tried it.
pack buildpack package
a composite buildpackpack builder create
the builderI worry that this will create problems with metadata though. 🤔
Additional context
This is a fairly urgent need for Paketo. We have hit the layer limit in our Paketo builders and are struggling to add new functionality because we can't add any more layers.
The text was updated successfully, but these errors were encountered: