-
-
Notifications
You must be signed in to change notification settings - Fork 15.1k
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
dockerTools.buildImage layers are 2x too big #94636
Comments
Is someone actively working on this? I'm willing, if not able, to help. |
I wonder if #108416 helps out here too.. |
Just briefy looking at the issue, Here is what I currently am thinking:
I am not actively working on this, but I do not know if someone else is.
I am not sure, but I'll assume that it is true for the rest of the comment. If there is an easy fix for the current implementation we should try it first.
I, for one, think it would be valuable to try to unify the codepaths of I guess another approach would be to just refactor @roberth What do you think? |
For the record, I have stopped using either Instead, I ended writing my own script (in Gerbil Scheme) that uses |
@utdemir Unifying would be great. Right now we have both duplicate maintenance and features that are missing in the one or the other. The two are quite different though, but I'm sure something can be done. Just unifying doesn't address the confusion around image
The
See #48462 |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: |
It looks like build dependencies are included in the resulting image, increasing the size by at least 30MB. pkgs.dockerTools.buildLayeredImage {
name = "hello-test";
tag = "latest";
contents = [ pkgs.hello ]; # pkgs.hello includes: libunistring, libidn2, glibc.
} Most of the images that I am trying to build include the following transitive build dependencies:
This means that it seems currently impossible to build Docker images that are smaller than 30MB using nix. I believe the build dependencies are included, because if I set Here are the layers according to Does anyone know how to take an existing derivation, e.g. p7zip, and remove dependencies 1 - 5 from its runtime dependencies, so that buildImage/buildLayeredImage will not include those layers? |
since #116749 is now merged, if you just want to change ownership of files in the image, you can switch to buildLayeredImage (streamLayeredImage), which doesn't have this problem. |
I marked this as stale due to inactivity. → More info |
This may help: #179801 |
@roberth |
Yeah I think that's because of You could probably make it work somehow, but for the dockertools project, I think we should leverage parts of NixOS
|
Yes, I wish I could use bits and pieces of NixOS. For now, I ended up moving sudo to a separate layer and that seems to work (I posted the workaround to that discord thread). Is it worth trying to switch to |
there’s only 120 something layers available so not exactly streamLayeredImage will put “most popular” packages into their own layer and once layer limit is reached lump everting that’s left into one final layer. This approach is suboptimal for most cases when the layer limit is reached. To optimise things for your use case you’d need something like this or alternatively this (haven’t used the latter) |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/dockertools-image-sizes-are-absurd-how-to-improve/49225/2 |
Describe the bug
When using dockerTools.buildImage, files specified as contents get added twice, resulting in an image twice too big: first by mkPureLayer (or mkRootLayer), without the /nix/store/* prefix path, directly in /, then by the layerClosures and newFiles handling of buildImage, that will pull in all the very same packages in /nix/store as separate copies.
To Reproduce
${IMG}
usingbuildImage
, thendocker load < result
docker run -t -i ${IMG} ls -lid /bin/bash /nix/store/*bash-interactive*/bin/bash
You'll see that the two files have different inode numbers. The same data is copied twice.
Or you can
docker history ${IMG}
and see that layers are twice the expected size.Expected behavior
Somehow the files should be copied only once. The two copies should be either as symlinks or hardlinks. In the latter case, the two steps of mkPureLayer then newFiles handling should happen in a single command that can thus share the hardlinks.
This requires some major refactoring of buildImage.
For added points, separate layer computation from image computation, so when chaining multiple layers, we don't need to pack then unpack N images each of N layers, which consumes O(N^2) resources both in cpu time and disk space.
For yet more points, make it so that layers can be built that are independent from each other will be built in parallel, instead of requiring a total order of layers.
Bonus: instead of running runAsRoot commands in a virtual machine, what about using the much lighter weight fakeroot, just like Debian does. This might even remove the need for two vastly separate cases mkPureLayer vs mkRootLayer.
Screenshots
If applicable, add screenshots to help explain your problem.
Additional context
Add any other context about the problem here.
Notify maintainers
@roberth @utdemir @alexbiehl @nlewo @grahamc
The text was updated successfully, but these errors were encountered: