如何独立于主机的 Nixos 配置构建或测试较小的 nixos 容器配置?

How can a build or test a smaller nixos container config independent of my host's Nixos config?

我正在尝试在 nixos containers 中配置一个容器,例如:

  containers.abc123 = {
    config = { config, pkgs, ... }:
    {
      systemd.services = {
        finder-email-requests = {
          description = "";
          enable = true;
          environment = {
              TESTING = "abcxyz";
          };
          serviceConfig = {
            Type      = "simple";

            ExecStart = "bash -c \"echo '$TESTING hello' >> /tmp/abcxyz\"";
            Restart   = "always";
            RestartSec   = 30;
          };
          wantedBy = [ "default.target" ];
        };
      };
    };
  };

但是需要 test/compile 这意味着 运行 nixos-rebuild test 这在我的机器上可能需要 10 秒以上(或者在我刚试过的新安装的 VM 上需要 7 秒)。

有没有什么方法可以独立于我的整个主机的 Nixos 配置更快地测试这个容器配置?例如只构建容器配置本身而不是这个容器的整个实例nixos 配置?


我发现 nixos-rebuild 命令是一个小的 shell 脚本,例如 https://github.com/NixOS/nixpkgs/blob/216f0e6ee4a65219f37caed95afda1a2c66188dc/nixos/modules/installer/tools/nixos-rebuild.sh

但是看完之后,我不太明白这个'containers'单元和一般'nixos config'之间的关系是怎么回事。

NixOS 容器没有自己的测试设施(截至 2020 年 11 月)。在大多数情况下,它们的行为与普通的 NixOS 系统一样。如果你想测试你的容器,正常的 NixOS 测试应该足够了。

在 NixOS 手册中 documented 编写 NixOS 测试。您可以使用 pkgs.nixosTest 函数在 Nixpkgs 存储库之外编写您自己的测试。

您可以使用您的容器测试主机系统的近似值,或者仅测试容器配置,就好像它是“顶级”NixOS 系统一样。我会选择后者,除非您需要同时测试多个容器,或者如果您需要测试主机和容器之间的交互。

但是为了正确测试容器定义构建,我们可以使用pkg.nixos。例如,容器的 nix 表达式(可以使用通常的 nix-build 方法构建):

{ a = let pkgs = import <nixpkgs> {};
in (pkgs.nixos
{
  fileSystems."/".device = "x";
  boot.loader.grub.enable = false;

  systemd.services = {
          finder-email-requests-2 = {
            description = "";
            enable = true;
            environment = {
                TESTING = "abcxyz";
            };
            serviceConfig = {
              Type      = "simple";

              ExecStart = "bash -c \"echo '$TESTING hello' >> /tmp/abcxyz\"";
              Restart   = "always";
              RestartSec   = 30;
            };
            wantedBy = [ "default.target" ];
          };
        };
}).toplevel; 
}