nixos/docker-containers: add imageFile and dependsOn options

- the `imageFile` option allows to load an image from a derivation
- the  `dependsOn` option can be used to specify dependencies between container systemd units.

Co-authored-by: Christian Höppner <mkaito@users.noreply.github.com>
This commit is contained in:
Yorick 2020-01-28 22:00:54 +01:00 committed by lewo
parent be52945974
commit 508343962e
2 changed files with 52 additions and 12 deletions

View File

@ -10,11 +10,24 @@ let
options = {
image = mkOption {
type = types.str;
type = with types; str;
description = "Docker image to run.";
example = "library/hello-world";
};
imageFile = mkOption {
type = with types; nullOr package;
default = null;
description = ''
Path to an image file to load instead of pulling from a registry.
If defined, do not pull from registry.
You still need to set the <literal>image</literal> attribute, as it
will be used as the image name for docker to start a container.
'';
example = literalExample "pkgs.dockerTools.buildDockerImage {...};";
};
cmd = mkOption {
type = with types; listOf str;
default = [];
@ -153,6 +166,24 @@ let
example = "/var/lib/hello_world";
};
dependsOn = mkOption {
type = with types; listOf str;
default = [];
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 <literal>services.docker-containers</literal>.
'';
example = literalExample ''
services.docker-containers = {
node1 = {};
node2 = {
dependsOn = [ "node1" ];
}
}
'';
};
extraDockerOptions = mkOption {
type = with types; listOf str;
default = [];
@ -164,15 +195,18 @@ let
};
};
mkService = name: container: {
mkService = name: container: let
mkAfter = map (x: "docker-${x}.service") container.dependsOn;
in rec {
wantedBy = [ "multi-user.target" ];
after = [ "docker.service" "docker.socket" ];
requires = [ "docker.service" "docker.socket" ];
after = [ "docker.service" "docker.socket" ] ++ mkAfter;
requires = after;
serviceConfig = {
ExecStart = concatStringsSep " \\\n " ([
"${pkgs.docker}/bin/docker run"
"--rm"
"--name=%n"
"--name=${name}"
"--log-driver=${container.log-driver}"
] ++ optional (container.entrypoint != null)
"--entrypoint=${escapeShellArg container.entrypoint}"
@ -185,9 +219,14 @@ let
++ [container.image]
++ map escapeShellArg container.cmd
);
ExecStartPre = "-${pkgs.docker}/bin/docker rm -f %n";
ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || ${pkgs.docker}/bin/docker stop %n"'';
ExecStopPost = "-${pkgs.docker}/bin/docker rm -f %n";
ExecStartPre = ["-${pkgs.docker}/bin/docker rm -f ${name}"
"-${pkgs.docker}/bin/docker image prune -f"] ++
(optional (container.imageFile != null)
["${pkgs.docker}/bin/docker load -i ${container.imageFile}"]);
ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || ${pkgs.docker}/bin/docker stop ${name}"'';
ExecStopPost = "-${pkgs.docker}/bin/docker rm -f ${name}";
### There is no generalized way of supporting `reload` for docker
### containers. Some containers may respond well to SIGHUP sent to their

View File

@ -1,9 +1,11 @@
# Test Docker containers as systemd units
import ./make-test.nix ({ pkgs, lib, ... }: {
import ./make-test.nix ({ pkgs, lib, ... }:
{
name = "docker-containers";
meta = {
maintainers = with lib.maintainers; [ benley ];
maintainers = with lib.maintainers; [ benley mkaito ];
};
nodes = {
@ -11,10 +13,9 @@ import ./make-test.nix ({ pkgs, lib, ... }: {
{
virtualisation.docker.enable = true;
virtualisation.dockerPreloader.images = [ pkgs.dockerTools.examples.nginx ];
docker-containers.nginx = {
image = "nginx-container";
imageFile = pkgs.dockerTools.examples.nginx;
ports = ["8181:80"];
};
};