From 2f7747526cc80844a506c4aa14706429324be157 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Mon, 20 Apr 2020 12:31:07 +0100 Subject: [PATCH] nixos/docker-containers: Rename to virtualisation.oci-containers.containers. And allow the runtime to be configurable via the `virtualisation.oci-containers.backend` option. Valid choices are "podman" and "docker". --- nixos/doc/manual/release-notes/rl-2009.xml | 6 + nixos/modules/module-list.nix | 2 +- ...cker-containers.nix => oci-containers.nix} | 118 ++++++++++++------ nixos/modules/virtualisation/podman.nix | 12 +- nixos/tests/all-tests.nix | 2 +- nixos/tests/docker-containers.nix | 27 ---- nixos/tests/oci-containers.nix | 43 +++++++ 7 files changed, 142 insertions(+), 68 deletions(-) rename nixos/modules/virtualisation/{docker-containers.nix => oci-containers.nix} (72%) delete mode 100644 nixos/tests/docker-containers.nix create mode 100644 nixos/tests/oci-containers.nix diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml index 78b8eee47efe..c6a766cc045a 100644 --- a/nixos/doc/manual/release-notes/rl-2009.xml +++ b/nixos/doc/manual/release-notes/rl-2009.xml @@ -55,6 +55,12 @@ The new virtualisation.containers module manages configuration shared by the CRI-O and Podman modules. + + + Declarative Docker containers are renamed from docker-containers to virtualisation.oci-containers.containers. + This is to make it possible to use podman instead of docker. + + diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 0cd17775e516..28f536056bf1 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -984,9 +984,9 @@ ./virtualisation/container-config.nix ./virtualisation/containers.nix ./virtualisation/nixos-containers.nix + ./virtualisation/oci-containers.nix ./virtualisation/cri-o.nix ./virtualisation/docker.nix - ./virtualisation/docker-containers.nix ./virtualisation/ecs-agent.nix ./virtualisation/libvirtd.nix ./virtualisation/lxc.nix diff --git a/nixos/modules/virtualisation/docker-containers.nix b/nixos/modules/virtualisation/oci-containers.nix similarity index 72% rename from nixos/modules/virtualisation/docker-containers.nix rename to nixos/modules/virtualisation/oci-containers.nix index 5ab990a3d7cc..a46dd65eb491 100644 --- a/nixos/modules/virtualisation/docker-containers.nix +++ b/nixos/modules/virtualisation/oci-containers.nix @@ -1,17 +1,20 @@ -{ config, lib, pkgs, ... }: +{ config, options, lib, pkgs, ... }: with lib; let - cfg = config.docker-containers; + cfg = config.virtualisation.oci-containers; + proxy_env = config.networking.proxy.envVars; - dockerContainer = + defaultBackend = options.virtualisation.oci-containers.backend.default; + + containerOptions = { ... }: { options = { image = mkOption { type = with types; str; - description = "Docker image to run."; + description = "OCI image to run."; example = "library/hello-world"; }; @@ -58,18 +61,19 @@ let log-driver = mkOption { type = types.str; - default = "none"; + default = "journald"; description = '' Logging driver for the container. The default of - "none" means that the container's logs will be - handled as part of the systemd unit. Setting this to - "journald" will result in duplicate logging, but - the container's logs will be visible to the docker - logs command. + "journald" means that the container's logs will be + handled as part of the systemd unit. - For more details and a full list of logging drivers, refer to the - - Docker engine documentation + For more details and a full list of logging drivers, refer to respective backends documentation. + + For Docker: + Docker engine documentation + + For Podman: + Refer to the docker-run(1) man page. ''; }; @@ -172,10 +176,10 @@ let description = '' Define which other containers this one depends on. They will be added to both After and Requires for the unit. - Use the same name as the attribute under services.docker-containers. + Use the same name as the attribute under virtualisation.oci-containers. ''; example = literalExample '' - services.docker-containers = { + virtualisation.oci-containers = { node1 = {}; node2 = { dependsOn = [ "node1" ]; @@ -184,10 +188,10 @@ let ''; }; - extraDockerOptions = mkOption { + extraOptions = mkOption { type = with types; listOf str; default = []; - description = "Extra options for docker run."; + description = "Extra options for ${defaultBackend} run."; example = literalExample '' ["--network=host"] ''; @@ -205,24 +209,31 @@ let }; mkService = name: container: let - mkAfter = map (x: "docker-${x}.service") container.dependsOn; - in rec { + dependsOn = map (x: "${cfg.backend}-${x}.service") container.dependsOn; + in { wantedBy = [] ++ optional (container.autoStart) "multi-user.target"; - after = [ "docker.service" "docker.socket" ] ++ mkAfter; - requires = after; - path = [ pkgs.docker ]; + after = lib.optionals (cfg.backend == "docker") [ "docker.service" "docker.socket" ] ++ dependsOn; + requires = dependsOn; + environment = proxy_env; + + path = + if cfg.backend == "docker" then [ pkgs.docker ] + else if cfg.backend == "podman" then [ config.virtualisation.podman.package ] + else throw "Unhandled backend: ${cfg.backend}"; preStart = '' - docker rm -f ${name} || true + ${cfg.backend} rm -f ${name} || true ${optionalString (container.imageFile != null) '' - docker load -i ${container.imageFile} + ${cfg.backend} load -i ${container.imageFile} ''} ''; - postStop = "docker rm -f ${name} || true"; - + postStop = "${cfg.backend} rm -f ${name} || true"; + serviceConfig = { + StandardOutput = "null"; + StandardError = "null"; ExecStart = concatStringsSep " \\\n " ([ - "${pkgs.docker}/bin/docker run" + "${config.system.path}/bin/${cfg.backend} run" "--rm" "--name=${name}" "--log-driver=${container.log-driver}" @@ -233,12 +244,12 @@ let ++ optional (container.user != null) "-u ${escapeShellArg container.user}" ++ map (v: "-v ${escapeShellArg v}") container.volumes ++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}" - ++ map escapeShellArg container.extraDockerOptions + ++ map escapeShellArg container.extraOptions ++ [container.image] ++ map escapeShellArg container.cmd ); - ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || docker stop ${name}"''; + ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || ${cfg.backend} stop ${name}"''; ### There is no generalized way of supporting `reload` for docker ### containers. Some containers may respond well to SIGHUP sent to their @@ -263,19 +274,50 @@ let }; in { + imports = [ + ( + lib.mkChangedOptionModule + [ "docker-containers" ] + [ "virtualisation" "oci-containers" ] + (oldcfg: { + backend = "docker"; + containers = lib.mapAttrs (n: v: builtins.removeAttrs (v // { + extraOptions = v.extraDockerOptions or []; + }) [ "extraDockerOptions" ]) oldcfg.docker-containers; + }) + ) + ]; - options.docker-containers = mkOption { - default = {}; - type = types.attrsOf (types.submodule dockerContainer); - description = "Docker containers to run as systemd services."; - }; + options.virtualisation.oci-containers = { - config = mkIf (cfg != {}) { + backend = mkOption { + type = types.enum [ "podman" "docker" ]; + default = + # TODO: Once https://github.com/NixOS/nixpkgs/issues/77925 is resolved default to podman + # if versionAtLeast config.system.stateVersion "20.09" then "podman" + # else "docker"; + "docker"; + description = "The underlying Docker implementation to use."; + }; - systemd.services = mapAttrs' (n: v: nameValuePair "docker-${n}" (mkService n v)) cfg; - - virtualisation.docker.enable = true; + containers = mkOption { + default = {}; + type = types.attrsOf (types.submodule containerOptions); + description = "OCI (Docker) containers to run as systemd services."; + }; }; + config = lib.mkIf (cfg.containers != {}) (lib.mkMerge [ + { + systemd.services = mapAttrs' (n: v: nameValuePair "${cfg.backend}-${n}" (mkService n v)) cfg.containers; + } + (lib.mkIf (cfg.backend == "podman") { + virtualisation.podman.enable = true; + }) + (lib.mkIf (cfg.backend == "docker") { + virtualisation.docker.enable = true; + }) + ]); + } diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index 1dc79272ccb6..9f98c2086d10 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -88,11 +88,21 @@ in }; }; + package = lib.mkOption { + type = types.package; + default = podmanPackage; + internal = true; + description = '' + The final Podman package (including extra packages). + ''; + }; + + }; config = lib.mkIf cfg.enable { - environment.systemPackages = [ podmanPackage ] + environment.systemPackages = [ cfg.package ] ++ lib.optional cfg.dockerCompat dockerCompat; environment.etc."containers/libpod.conf".text = '' diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index eff1752bbbf8..ebb0dfef15ac 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -70,7 +70,7 @@ in dhparams = handleTest ./dhparams.nix {}; dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {}; docker = handleTestOn ["x86_64-linux"] ./docker.nix {}; - docker-containers = handleTestOn ["x86_64-linux"] ./docker-containers.nix {}; + oci-containers = handleTestOn ["x86_64-linux"] ./oci-containers.nix {}; docker-edge = handleTestOn ["x86_64-linux"] ./docker-edge.nix {}; docker-preloader = handleTestOn ["x86_64-linux"] ./docker-preloader.nix {}; docker-registry = handleTest ./docker-registry.nix {}; diff --git a/nixos/tests/docker-containers.nix b/nixos/tests/docker-containers.nix deleted file mode 100644 index 0e318a52d9f1..000000000000 --- a/nixos/tests/docker-containers.nix +++ /dev/null @@ -1,27 +0,0 @@ -# Test Docker containers as systemd units - -import ./make-test-python.nix ({ pkgs, lib, ... }: { - name = "docker-containers"; - meta = { - maintainers = with lib.maintainers; [ benley mkaito ]; - }; - - nodes = { - docker = { pkgs, ... }: { - virtualisation.docker.enable = true; - - docker-containers.nginx = { - image = "nginx-container"; - imageFile = pkgs.dockerTools.examples.nginx; - ports = ["8181:80"]; - }; - }; - }; - - testScript = '' - start_all() - docker.wait_for_unit("docker-nginx.service") - docker.wait_for_open_port(8181) - docker.wait_until_succeeds("curl http://localhost:8181 | grep Hello") - ''; -}) diff --git a/nixos/tests/oci-containers.nix b/nixos/tests/oci-containers.nix new file mode 100644 index 000000000000..bb6c019f07c9 --- /dev/null +++ b/nixos/tests/oci-containers.nix @@ -0,0 +1,43 @@ +{ 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 = with lib.maintainers; [ adisbladis benley mkaito ]; + }; + + nodes = { + ${backend} = { pkgs, ... }: { + virtualisation.oci-containers = { + inherit backend; + containers.nginx = { + image = "nginx-container"; + imageFile = pkgs.dockerTools.examples.nginx; + ports = ["8181:80"]; + }; + }; + }; + }; + + testScript = '' + start_all() + ${backend}.wait_for_unit("${backend}-nginx.service") + ${backend}.wait_for_open_port(8181) + ${backend}.wait_until_succeeds("curl http://localhost:8181 | grep Hello") + ''; + }; + +in +lib.foldl' (attrs: backend: attrs // { ${backend} = mkOCITest backend; }) {} [ + "docker" + "podman" +]