Controling which packages goes into which layer with dockerTools.streamLayeredImage

Hi everyone,
I am building a container using dockerTools.streamLayeredImage with quite a lot of tools ready for my coworkers (the resulting image is over 27GB). The result is great and works all fine.

I have however trouble controlling the layering of the resulting docker image. I have all the pkgs separated into multiple files (representing the category of the tools) and i would like to keep this separation for the docker layers and i couldn’t find how to do that.

This example in nixpkgs on github states that you can do a succession of buildImage, with each of them based on the previous one (via fromImage), but then for 10 layers that does duplicate the first one 10 times, the 2nd 9 times and so on. I ran out of disk space before being able to build.

As of now, each pkgs have their own layer, up until the layer limit is reached where the last layer holds every remaining pkgs (that layer is 25GB worth right now). This kind of defeats the layering from being useful as its so big that it will almost always be updated.

Here is a simplified version of my flake with only 1 set of tools:

{
  description = "Docker image with prepackaged tools";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/25.05";
  };

  outputs = { self, nixpkgs }:
    let
      system = "x86_64-linux";
      pkgs = import nixpkgs {
        inherit system;
        config.allowUnfree = true;
      };
      adTools = import ./tools-packages/ad.nix pkgs;
      layerAdTools = pkgs.buildEnv {
        name = "layer-adTools";
        paths = adTools;
      };
      nix-img = pkgs.dockerTools.streamLayeredImage {
        name = "ctr-nix";
        tag = "latest";
        contents = with pkgs; [
          shadow
          nix
          gnused
          coreutils-full
          dockerTools.usrBinEnv
          dockerTools.binSh
          dockerTools.caCertificates
          dockerTools.fakeNss
          bash
          layerAdTools
        ];
        maxLayers = 100;
        includeNixDB = true;
        created = "now";
        config = {
          User = "root";
        };
      };
    in
    {
      formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.nixpkgs-fmt;
      packages.${system} = {
        default = nix-img;
      };
    };
}

and ad.nix looks like this (again, shortened):

pkgs: with pkgs; [
  smbclient-ng
]

Ideally i wish i could have layers built based on the category of the tools so that we could have smaller layers (or actually any other clever grouping you might suggest :smiley:)

1 Like