docker: add option to prune all volumes when auto pruning (#508604)

This commit is contained in:
Maximilian Bosch
2026-05-14 11:40:08 +00:00
committed by GitHub
3 changed files with 115 additions and 9 deletions
+57 -9
View File
@@ -157,6 +157,14 @@ in
Whether to periodically prune Docker resources. If enabled, a
systemd timer will run `docker system prune -f`
as specified by the `dates` option.
NOTE: by default this does not prune volumes. Anonymous volumes
can be pruned by passing "--volumes" to [autoPrune.flags](#opt-virtualisation.docker.autoPrune.flags).
To prune all volumes (not just anonymous ones) [`autoPrune.allVolumes.enable`](#opt-virtualisation.docker.autoPrune.allVolumes.enable)
must be used.
See [upstream documentation](https://docs.docker.com/reference/cli/docker/system/prune/#description) for further information.
'';
};
@@ -206,6 +214,28 @@ in
system was powered down.
'';
};
allVolumes = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to periodically prune all Docker volumes when auto pruning other docker resources
by running {command}`docker volume prune --force --all`
To prune only anonymous volumes, instead pass `--volumes` to `autoPrune.flags`
'';
};
flags = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--filter=label=<label>" ];
description = ''
Any additional flags passed to {command}`docker volume prune --force --all`.
'';
};
};
};
package = mkPackageOption pkgs "docker" { };
@@ -312,15 +342,29 @@ in
serviceConfig = {
Type = "oneshot";
ExecStart = utils.escapeSystemdExecArgs (
[
(lib.getExe cfg.package)
"system"
"prune"
"-f"
]
++ cfg.autoPrune.flags
);
ExecStart = [
(utils.escapeSystemdExecArgs (
[
(lib.getExe cfg.package)
"system"
"prune"
"-f"
]
++ cfg.autoPrune.flags
))
]
++ (optionals cfg.autoPrune.allVolumes.enable [
(utils.escapeSystemdExecArgs (
[
(lib.getExe cfg.package)
"volume"
"prune"
"--force"
"--all"
]
++ cfg.autoPrune.allVolumes.flags
))
]);
};
startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates;
@@ -342,6 +386,10 @@ in
-> config.hardware.graphics.enable32Bit or false;
message = "Option enableNvidia on x86_64 requires 32-bit support libraries";
}
{
assertion = cfg.autoPrune.allVolumes.enable -> cfg.autoPrune.enable;
message = "Option autoPrune.allVolumes.enable requires autoPrune.enable";
}
];
virtualisation.docker.daemon.settings = {
+1
View File
@@ -467,6 +467,7 @@ in
dnsdist = import ./dnsdist.nix { inherit pkgs runTest; };
doas = runTest ./doas.nix;
docker = runTestOn [ "aarch64-linux" "x86_64-linux" ] ./docker.nix;
docker-autoprune = runTestOn [ "aarch64-linux" "x86_64-linux" ] ./docker-autoprune.nix;
docker-registry = runTest ./docker-registry.nix;
docker-rootless = runTestOn [ "aarch64-linux" "x86_64-linux" ] ./docker-rootless.nix;
docker-tools = runTestOn [ "x86_64-linux" ] ./docker-tools.nix;
+57
View File
@@ -0,0 +1,57 @@
# This test validates the docker autoprune service, testing whether
# the default configuration cleans up images, while leaving volumes intact
# and whether the allVolumes option enables cleaning up volumes as well
{ pkgs, ... }:
{
name = "docker";
nodes = {
prune =
{ pkgs, ... }:
{
virtualisation.docker = {
enable = true;
package = pkgs.docker;
autoPrune = {
enable = true;
};
};
};
prunevolumes =
{ pkgs, ... }:
{
virtualisation.docker = {
enable = true;
package = pkgs.docker;
autoPrune = {
enable = true;
allVolumes.enable = true;
};
};
};
};
testScript = ''
start_all()
with subtest("Check whether autoPrune works. Volumes should be left unpruned."):
prune.wait_for_unit("sockets.target")
prune.succeed("docker network create testnetwork")
prune.succeed("docker network list --format json | grep testnetwork")
prune.succeed("docker volume create testvolume")
prune.succeed("docker volume list --format json | grep testvolume")
prune.succeed("systemctl start -v docker-prune")
prune.fail("docker network list --format json | grep testnetwork")
# the volume has been left alone
prune.succeed("docker volume list --format json | grep testvolume")
with subtest("Check whether autoPrune including volumes works"):
prunevolumes.wait_for_unit("sockets.target")
prunevolumes.succeed("docker volume create testvolume")
prunevolumes.succeed("docker volume list --format json | grep testvolume")
prunevolumes.succeed("systemctl start -v docker-prune")
prunevolumes.fail("docker volume list --format json | grep testvolume")
'';
}