mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-10 19:55:41 +03:00

Closes #259770 Closes #207050 The motivation for the former is to not execute the container as root, so you don't have to `sudo -i` to perform podman management tasks. The idea behind healthchecks is to be able to keep the unit in the activating state until the container is healthy, only then then unit is marked as active. The following changes were necessary: * Move the ctr-id into `/run/${containerName}` to make podman can actually write to it since it's now in its RuntimeDirectory. * Make `sdnotify` option configurable (`healthy` for healthchecks that must pass, default remains `conmon`). * Set Delegate=yes for `sdnotify=healthy` to make sure a rootless container can actually talk to sd_notify[1]. * Add a warning that lingering must be enabled to have a `systemd --user` instance running which is required for the cgroup support to work properly. * Added a testcase for rootless containers with both conmon and healthchecks. [1] https://github.com/containers/podman/discussions/20573#discussioncomment-7612481
127 lines
4 KiB
Nix
127 lines
4 KiB
Nix
{
|
|
system ? builtins.currentSystem,
|
|
config ? { },
|
|
pkgs ? import ../.. { inherit system config; },
|
|
lib ? pkgs.lib,
|
|
}:
|
|
|
|
let
|
|
|
|
inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest;
|
|
|
|
mkOCITest =
|
|
backend:
|
|
makeTest {
|
|
name = "oci-containers-${backend}";
|
|
|
|
meta.maintainers = lib.teams.serokell.members ++ (with lib.maintainers; [ benley ]);
|
|
|
|
nodes = {
|
|
${backend} =
|
|
{ pkgs, ... }:
|
|
{
|
|
virtualisation.oci-containers = {
|
|
inherit backend;
|
|
containers.nginx = {
|
|
image = "nginx-container";
|
|
imageStream = pkgs.dockerTools.examples.nginxStream;
|
|
ports = [ "8181:80" ];
|
|
capabilities = {
|
|
CAP_AUDIT_READ = true;
|
|
CAP_AUDIT_WRITE = false;
|
|
};
|
|
privileged = false;
|
|
devices = [
|
|
"/dev/random:/dev/random"
|
|
];
|
|
};
|
|
};
|
|
|
|
# Stop systemd from killing remaining processes if ExecStop script
|
|
# doesn't work, so that proper stopping can be tested.
|
|
systemd.services."${backend}-nginx".serviceConfig.KillSignal = "SIGCONT";
|
|
};
|
|
};
|
|
|
|
testScript = ''
|
|
import json
|
|
|
|
start_all()
|
|
${backend}.wait_for_unit("${backend}-nginx.service")
|
|
${backend}.wait_for_open_port(8181)
|
|
${backend}.wait_until_succeeds("curl -f http://localhost:8181 | grep Hello")
|
|
output = json.loads(${backend}.succeed("${backend} inspect nginx --format json").strip())[0]
|
|
${backend}.succeed("systemctl stop ${backend}-nginx.service", timeout=10)
|
|
assert output['HostConfig']['CapAdd'] == ["CAP_AUDIT_READ"]
|
|
assert output['HostConfig']['CapDrop'] == ${
|
|
if backend == "docker" then "[\"CAP_AUDIT_WRITE\"]" else "[]"
|
|
} # Rootless podman runs with no capabilities so it cannot drop them
|
|
assert output['HostConfig']['Privileged'] == False
|
|
assert output['HostConfig']['Devices'] == [{'PathOnHost': '/dev/random', 'PathInContainer': '/dev/random', 'CgroupPermissions': '${
|
|
if backend == "docker" then "rwm" else ""
|
|
}'}]
|
|
'';
|
|
};
|
|
|
|
podmanRootlessTests = lib.genAttrs [ "conmon" "healthy" ] (
|
|
type:
|
|
makeTest {
|
|
name = "oci-containers-podman-rootless-${type}";
|
|
meta.maintainers = lib.teams.flyingcircus.members;
|
|
nodes = {
|
|
podman =
|
|
{ pkgs, ... }:
|
|
{
|
|
environment.systemPackages = [ pkgs.redis ];
|
|
users.groups.redis = { };
|
|
users.users.redis = {
|
|
isSystemUser = true;
|
|
group = "redis";
|
|
home = "/var/lib/redis";
|
|
linger = type == "healthy";
|
|
createHome = true;
|
|
subUidRanges = [
|
|
{
|
|
count = 65536;
|
|
startUid = 2147483646;
|
|
}
|
|
];
|
|
subGidRanges = [
|
|
{
|
|
count = 65536;
|
|
startGid = 2147483647;
|
|
}
|
|
];
|
|
};
|
|
virtualisation.oci-containers = {
|
|
backend = "podman";
|
|
containers.redis = {
|
|
image = "redis:latest";
|
|
imageFile = pkgs.dockerTools.examples.redis;
|
|
ports = [ "6379:6379" ];
|
|
podman = {
|
|
user = "redis";
|
|
sdnotify = type;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
testScript = ''
|
|
start_all()
|
|
podman.wait_for_unit("podman-redis.service")
|
|
${lib.optionalString (type != "healthy") ''
|
|
podman.wait_for_open_port(6379)
|
|
''}
|
|
podman.wait_until_succeeds("set -eo pipefail; echo 'keys *' | redis-cli")
|
|
'';
|
|
}
|
|
);
|
|
in
|
|
{
|
|
docker = mkOCITest "docker";
|
|
podman = mkOCITest "podman";
|
|
podman-rootless-conmon = podmanRootlessTests.conmon;
|
|
podman-rootless-healthy = podmanRootlessTests.healthy;
|
|
}
|