diff options
author | Louis Blin <45168934+lbpdt@users.noreply.github.com> | 2021-03-25 16:38:37 +0000 |
---|---|---|
committer | Louis Blin <45168934+lbpdt@users.noreply.github.com> | 2021-03-25 23:29:54 +0000 |
commit | b3f68289df646a82c9b87d866244510ff1d2866a (patch) | |
tree | 67e0cfe413bf7f94974c738ea9d12d3626d6a46a | |
parent | 06733bcf290555154666410f2fb30ee4a2aba6c0 (diff) |
dockerTools.streamLayeredImage: resolve duplicate env vars
For images running on Kubernetes, there is no guarantee on how duplicate environment variables in the image config will be handled. This seems to be different from Docker, where the last environment variable value is consistently selected. The current code for `streamLayeredImage` was exploiting that assumption to easily propagate environment variables from the base image, leaving duplicates unchecked. It should rather resolve these duplicates to ensure consistent behavior on Docker and Kubernetes.
-rw-r--r-- | nixos/tests/docker-tools.nix | 15 | ||||
-rw-r--r-- | pkgs/build-support/docker/stream_layered_image.py | 4 |
2 files changed, 18 insertions, 1 deletions
diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix index dd287883c9821..a0e81b613ce8f 100644 --- a/nixos/tests/docker-tools.nix +++ b/nixos/tests/docker-tools.nix @@ -221,6 +221,21 @@ import ./make-test-python.nix ({ pkgs, ... }: { assert "FROM_CHILD=true" in env, "envvars from the child should be preserved" assert "LAST_LAYER=child" in env, "envvars from the child should take priority" + with subtest( + "Ensure inherited environment variables of layered images are correctly resolved" + ): + # Read environment variables as stored in image config + config = docker.succeed( + "tar -xOf ${examples.environmentVariablesLayered} manifest.json | ${pkgs.jq}/bin/jq -r .[].Config" + ).strip() + out = docker.succeed( + f"tar -xOf ${examples.environmentVariablesLayered} {config} | ${pkgs.jq}/bin/jq -r '.config.Env | .[]'" + ) + env = out.splitlines() + assert ( + sum(entry.startswith("LAST_LAYER") for entry in env) == 1 + ), "envvars overridden by child should be unique" + with subtest("Ensure image with only 2 layers can be loaded"): docker.succeed( "docker load --input='${examples.two-layered-image}'" diff --git a/pkgs/build-support/docker/stream_layered_image.py b/pkgs/build-support/docker/stream_layered_image.py index 3e5781ba1c806..d7c63eb43a78f 100644 --- a/pkgs/build-support/docker/stream_layered_image.py +++ b/pkgs/build-support/docker/stream_layered_image.py @@ -202,7 +202,9 @@ def overlay_base_config(from_image, final_config): # Preserve environment from base image final_env = base_config.get("Env", []) + final_config.get("Env", []) if final_env: - final_config["Env"] = final_env + # Resolve duplicates (last one wins) and format back as list + resolved_env = {entry.split("=", 1)[0]: entry for entry in final_env} + final_config["Env"] = list(resolved_env.values()) return final_config |