Skip to content
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

Expose copyTo* functions in default.nix #158

Closed
bengsparks opened this issue Dec 12, 2024 · 1 comment
Closed

Expose copyTo* functions in default.nix #158

bengsparks opened this issue Dec 12, 2024 · 1 comment

Comments

@bengsparks
Copy link

Motivation:

Building executable images for other architectures is not very simple.

Background:

I've been recently learning to build images with nix2container on my Mac M2, and I struggled to correctly build an image in my flake.nix that could then be run in Docker.

flake.nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
    flake-utils.url = "github:numtide/flake-utils";
    nix2container.url = "github:nlewo/nix2container";
  };

  outputs = { nixpkgs, flake-utils, nix2container, ... }: flake-utils.lib.eachDefaultSystem
    (system:
      let
        pkgs = import nixpkgs { inherit system; };
        n2c = nix2container.packages.${system}.nix2container;
      in
      rec {
        packages = rec {
          hello = pkgs.hello;
          hello-image = n2c.buildImage
            {
              name = "hello";
              tag = "latest";
              config = {
                entrypoint = [ "hello" ];
              };
              copyToRoot = pkgs.buildEnv {
                name = "root";
                paths = [ hello ];
                pathsToLink = [ "/bin" ];
              };
            };
        };
      });
}

Results in:

$ nix run .#hello-image.copyToDockerDaemon
Copy to Docker daemon image hello:latest
Getting image source signatures
Copying blob aba2de13cf14 done   | 
Copying config 3e1fea8b5d done   | 
Writing manifest to image destination

$ docker run hello:latest
Cannot run macOS (Mach-O) executable in Docker: Exec format error

This is due to building the image for a different architecture than the container is executed on.

Solution:

My "fix" for this is to specify per-architecture packages that make use of copyToDockerDaemon, which I've adapted from the default.nix of this project:

Improved flake.nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
    flake-utils.url = "github:numtide/flake-utils";
    nix2container.url = "github:nlewo/nix2container";
  };

  outputs = { nixpkgs, flake-utils, nix2container, self, ... }: flake-utils.lib.eachDefaultSystem
    (system:
      let
        pkgs = import nixpkgs { inherit system; };

        n2c = nix2container.packages.${system}.nix2container;
        skopeo = nix2container.packages.${system}.skopeo-nix2container;

        # Adapted from nix2container's default.nix
        writeSkopeoApplication = name: text: pkgs.writeShellApplication {
          inherit name text;
          runtimeInputs = [ pkgs.jq skopeo ];
          excludeShellChecks = [ "SC2068" ];
        };
        copyToDockerDaemon = image: writeSkopeoApplication "copy-to-docker-daemon" ''
          echo "Copy to Docker daemon image ${image.imageName}:${image.imageTag}"
          skopeo --insecure-policy copy nix:${image} docker-daemon:${image.imageName}:${image.imageTag} $@
        '';
      in
      rec {
        packages = rec {
          hello = pkgs.hello;
          hello-image = n2c.buildImage
            {
              name = "hello";
              tag = "latest";
              config = {
                entrypoint = [ "hello" ];
              };
              copyToRoot = pkgs.buildEnv {
                name = "root";
                paths = [ hello ];
                pathsToLink = [ "/bin" ];
              };
            };

          # Always use the `aarch64-linux` package!
          hello-push = copyToDockerDaemon self.packages.aarch64-linux.hello-image;
        };
      });
}

Resulting in

$ nix run .#hello-push
Copy to Docker daemon image hello:latest
Getting image source signatures
Copying blob aba2de13cf14 done   | 
Copying config 3e1fea8b5d done   | 
Writing manifest to image destination

$ docker run hello:latest
Hello, world!

This is by no means a particularly pleasant solution, but exposing the copyTo* functions from the nix2container module would make this simpler.

Alternatively we wait for #153 to become stable (If I understand correctly, this PR would also fix this issue, and more?)

@bengsparks
Copy link
Author

bengsparks commented Feb 13, 2025

This can be closed;
Building packages for the hostSystem (i.e. the system the program shall run on) and using nix2container for the buildSystem (i.e. the system you are building on) is sufficient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant