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 = { options = {
image = mkOption { image = mkOption {
type = types.str; type = with types; str;
description = "Docker image to run."; description = "Docker image to run.";
example = "library/hello-world"; 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 { cmd = mkOption {
type = with types; listOf str; type = with types; listOf str;
default = []; default = [];
@ -153,6 +166,24 @@ let
example = "/var/lib/hello_world"; 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 { extraDockerOptions = mkOption {
type = with types; listOf str; type = with types; listOf str;
default = []; 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" ]; wantedBy = [ "multi-user.target" ];
after = [ "docker.service" "docker.socket" ]; after = [ "docker.service" "docker.socket" ] ++ mkAfter;
requires = [ "docker.service" "docker.socket" ]; requires = after;
serviceConfig = { serviceConfig = {
ExecStart = concatStringsSep " \\\n " ([ ExecStart = concatStringsSep " \\\n " ([
"${pkgs.docker}/bin/docker run" "${pkgs.docker}/bin/docker run"
"--rm" "--rm"
"--name=%n" "--name=${name}"
"--log-driver=${container.log-driver}" "--log-driver=${container.log-driver}"
] ++ optional (container.entrypoint != null) ] ++ optional (container.entrypoint != null)
"--entrypoint=${escapeShellArg container.entrypoint}" "--entrypoint=${escapeShellArg container.entrypoint}"
@ -185,9 +219,14 @@ let
++ [container.image] ++ [container.image]
++ map escapeShellArg container.cmd ++ 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"''; ExecStartPre = ["-${pkgs.docker}/bin/docker rm -f ${name}"
ExecStopPost = "-${pkgs.docker}/bin/docker rm -f %n"; "-${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 ### There is no generalized way of supporting `reload` for docker
### containers. Some containers may respond well to SIGHUP sent to their ### containers. Some containers may respond well to SIGHUP sent to their

View File

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