about summary refs log tree commit diff
path: root/nixos/modules/virtualisation/docker-containers.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/virtualisation/docker-containers.nix')
-rw-r--r--nixos/modules/virtualisation/docker-containers.nix73
1 files changed, 62 insertions, 11 deletions
diff --git a/nixos/modules/virtualisation/docker-containers.nix b/nixos/modules/virtualisation/docker-containers.nix
index 59b0943f591f..5ab990a3d7cc 100644
--- a/nixos/modules/virtualisation/docker-containers.nix
+++ b/nixos/modules/virtualisation/docker-containers.nix
@@ -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 = [];
@@ -26,7 +39,7 @@ let
 
         entrypoint = mkOption {
           type = with types; nullOr str;
-          description = "Overwrite the default entrypoint of the image.";
+          description = "Override the default entrypoint of the image.";
           default = null;
           example = "/bin/my-app";
         };
@@ -132,7 +145,7 @@ let
 
             Note that this is a list of <literal>"src:dst"</literal> strings to
             allow for <literal>src</literal> to refer to
-            <literal>/nix/store</literal> paths, which would difficult with an
+            <literal>/nix/store</literal> paths, which would be difficult with an
             attribute set.  There are also a variety of mount options available
             as a third field; please refer to the
             <link xlink:href="https://docs.docker.com/engine/reference/run/#volume-shared-filesystems">
@@ -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 = [];
@@ -161,18 +192,39 @@ let
             ["--network=host"]
           '';
         };
+
+        autoStart = mkOption {
+          type = types.bool;
+          default = true;
+          description = ''
+            When enabled, the container is automatically started on boot.
+            If this option is set to false, the container has to be started on-demand via its service.
+          '';
+        };
       };
     };
 
-  mkService = name: container: {
-    wantedBy = [ "multi-user.target" ];
-    after = [ "docker.service" "docker.socket" ];
-    requires = [ "docker.service" "docker.socket" ];
+  mkService = name: container: let
+    mkAfter = map (x: "docker-${x}.service") container.dependsOn;
+  in rec {
+    wantedBy = [] ++ optional (container.autoStart) "multi-user.target";
+    after = [ "docker.service" "docker.socket" ] ++ mkAfter;
+    requires = after;
+    path = [ pkgs.docker ];
+
+    preStart = ''
+      docker rm -f ${name} || true
+      ${optionalString (container.imageFile != null) ''
+        docker load -i ${container.imageFile}
+        ''}
+      '';
+    postStop = "docker rm -f ${name} || true";
+        
     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 +237,8 @@ let
         ++ [container.image]
         ++ map escapeShellArg container.cmd
       );
-      ExecStartPre = "-${pkgs.docker}/bin/docker rm -f %n";
-      ExecStop = "${pkgs.docker}/bin/docker stop %n";
-      ExecStopPost = "-${pkgs.docker}/bin/docker rm -f %n";
+
+      ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || docker stop ${name}"'';
 
       ### There is no generalized way of supporting `reload` for docker
       ### containers. Some containers may respond well to SIGHUP sent to their