diff --git a/doc/builders/images/dockertools.section.md b/doc/builders/images/dockertools.section.md index 6203b3786bf..dfc012b80c5 100644 --- a/doc/builders/images/dockertools.section.md +++ b/doc/builders/images/dockertools.section.md @@ -62,6 +62,8 @@ The above example will build a Docker image `redis/latest` from the given base i - `config` is used to specify the configuration of the containers that will be started off the built image in Docker. The available options are listed in the [Docker Image Specification v1.2.0](https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions). +- `architecture` is _optional_ and used to specify the image architecture, this is useful for multi-architecture builds that don't need cross compiling. If not specified it will default to `hostPlatform`. + - `diskSize` is used to specify the disk size of the VM used to build the image in megabytes. By default it's 1024 MiB. - `buildVMMemorySize` is used to specify the memory size of the VM to build the image in megabytes. By default it's 512 MiB. @@ -141,6 +143,8 @@ Create a Docker image with many of the store paths being on their own layer to i `config` _optional_ +`architecture` is _optional_ and used to specify the image architecture, this is useful for multi-architecture builds that don't need cross compiling. If not specified it will default to `hostPlatform`. + : Run-time configuration of the container. A full list of the options are available at in the [Docker Image Specification v1.2.0](https://github.com/moby/moby/blob/master/image/spec/v1.2.md#image-json-field-descriptions). *Default:* `{}` diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix index e76a4613192..71ef9ecc5d7 100644 --- a/nixos/tests/docker-tools.nix +++ b/nixos/tests/docker-tools.nix @@ -419,6 +419,20 @@ import ./make-test-python.nix ({ pkgs, ... }: { "docker rmi layered-image-with-path", ) + with subtest("Ensure correct architecture is present in manifests."): + docker.succeed( + "docker load --input='${examples.build-image-with-architecture}'", + "docker inspect ${examples.build-image-with-architecture} " + + "| ${pkgs.jq}/bin/jq -er '.[] | select(.Architecture=="arm64").Architecture'", + "docker rmi build-image-with-architecture", + ) + docker.succeed( + "${examples.layered-image-with-architecture} | docker load", + "docker inspect ${examples.layered-image-with-architecture} " + + "| ${pkgs.jq}/bin/jq -er '.[] | select(.Architecture=="arm64").Architecture'", + "docker rmi layered-image-with-architecture", + ) + with subtest("etc"): docker.succeed("${examples.etc} | docker load") docker.succeed("docker run --rm etc | grep localhost") diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index c6ab4589aef..bc1b58a684f 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -101,8 +101,8 @@ rec { , imageDigest , sha256 , os ? "linux" - , arch ? defaultArch - + , # Image architecture, defaults to the architecture of the `hostPlatform` when unset + arch ? defaultArch # This is used to set name to the pulled image , finalImageName ? imageName # This used to set a tag to the pulled image @@ -514,6 +514,8 @@ rec { keepContentsDirlinks ? false , # Docker config; e.g. what command to run on the container. config ? null + , # Image architecture, defaults to the architecture of the `hostPlatform` when unset + architecture ? defaultArch , # Optional bash script to run on the files prior to fixturizing the layer. extraCommands ? "" , uid ? 0 @@ -546,8 +548,7 @@ rec { baseJson = let pure = writeText "${baseName}-config.json" (builtins.toJSON { - inherit created config; - architecture = defaultArch; + inherit created config architecture; preferLocalBuild = true; os = "linux"; }); @@ -838,6 +839,8 @@ rec { contents ? [ ] , # Docker config; e.g. what command to run on the container. config ? { } + , # Image architecture, defaults to the architecture of the `hostPlatform` when unset + architecture ? defaultArch , # Time of creation of the image. Passing "now" will make the # created date be the time of building. created ? "1970-01-01T00:00:01Z" @@ -869,8 +872,7 @@ rec { streamScript = writePython3 "stream" { } ./stream_layered_image.py; baseJson = writeText "${baseName}-base.json" (builtins.toJSON { - inherit config; - architecture = defaultArch; + inherit config architecture; os = "linux"; }); diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix index 71c3574963c..80661c1a7d9 100644 --- a/pkgs/build-support/docker/examples.nix +++ b/pkgs/build-support/docker/examples.nix @@ -700,6 +700,21 @@ rec { contents = [ pkgs.bashInteractive ./test-dummy ]; }; + build-image-with-architecture = buildImage { + name = "build-image-with-architecture"; + tag = "latest"; + architecture = "arm64"; + # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication. + copyToRoot = [ pkgs.bashInteractive ./test-dummy ]; + }; + + layered-image-with-architecture = pkgs.dockerTools.streamLayeredImage { + name = "layered-image-with-architecture"; + tag = "latest"; + architecture = "arm64"; + contents = [ pkgs.bashInteractive ./test-dummy ]; + }; + # ensure that caCertificates builds image-with-certs = buildImage { name = "image-with-certs";