diff options
-rw-r--r-- | modules/apps/docker/default.nix | 63 | ||||
-rw-r--r-- | modules/apps/docker/instance.nix | 109 |
2 files changed, 172 insertions, 0 deletions
diff --git a/modules/apps/docker/default.nix b/modules/apps/docker/default.nix new file mode 100644 index 0000000..7698959 --- /dev/null +++ b/modules/apps/docker/default.nix @@ -0,0 +1,63 @@ +{ config, pkgs, lib, ... }: + +let + + inherit (builtins) toJSON; + + inherit (lib) + filterAttrs foldl mapAttrsToList mkOption optional + ; + + inherit (lib.types) attrsOf submodule; + + explicit = filterAttrs (n: v: n != "_module" && v != null); + + instances = explicit config.nixsap.apps.docker; + + groups = mapAttrsToList (_: i: i.daemon.group) instances; + clis = mapAttrsToList (_: i: i.docker-cli) instances; + + mkService = name: opts: + let + config-file = pkgs.runCommand "dockerd-${name}.json" {} '' + cat <<'EOF' | ${pkgs.jq}/bin/jq . > $out + ${toJSON (explicit (opts.daemon))} + EOF + ''; + in { + "docker-${name}" = { + description = "Docker daemon (${name})"; + wantedBy = [ "multi-user.target" ]; + after = [ "local-fs.target" ]; + path = [ pkgs.kmod ] ++ (optional (opts.daemon.storage-driver == "zfs") pkgs.zfs); + preStart = '' + mkdir -p -- '${opts.daemon.data-root}' + rm -rf -- '${opts.daemon.exec-root}' + mkdir -p -- '${opts.daemon.exec-root}' + + chown -c -- 'root:root' '${opts.daemon.data-root}' + chmod -c -- u=rwX,g=rX,o= '${opts.daemon.data-root}' + ''; + serviceConfig = { + ExecStart = "${opts.package}/bin/dockerd --config-file ${config-file}"; + ExecReload = "${pkgs.procps}/bin/kill -s HUP $MAINPID"; + }; + }; + }; + +in { + + options.nixsap.apps.docker = mkOption { + description = "Instances of Docker"; + type = attrsOf (submodule (import ./instance.nix pkgs)); + default = {}; + }; + + config = { + systemd.services = foldl (a: b: a//b) {} (mapAttrsToList mkService instances); + nixsap.system.groups = groups; + environment.systemPackages = clis; + }; + +} + diff --git a/modules/apps/docker/instance.nix b/modules/apps/docker/instance.nix new file mode 100644 index 0000000..fc361f3 --- /dev/null +++ b/modules/apps/docker/instance.nix @@ -0,0 +1,109 @@ +pkgs: + +{ lib, name, config, ... }: + +let + + inherit (lib) + mkOption + ; + + inherit (lib.types) + bool enum int listOf nullOr package path str + ; + + default = d: t: mkOption { type = t; default = d; }; + optional = t: mkOption { type = nullOr t; default = null; }; + readonly = d: t: mkOption { type = nullOr t; default = d; readOnly = true; }; + + socket = "unix://${config.daemon.exec-root}/dockerd.sock"; + +in { + options = { + package = mkOption { + description = "Docker package"; + default = pkgs.docker; + type = package; + }; + + docker-cli = mkOption { + description = "Convenient wrapper of docker command line uitlity for this Docker instance"; + type = package; + readOnly = true; + default = pkgs.runCommand "docker-${name}" {} '' + mkdir -p $out/bin + mkdir -p $out/share/bash-completion/completions + + cat << 'ETC' > "$out/share/bash-completion/completions/docker-${name}" + . ${config.package}/share/bash-completion/completions/docker + complete -r docker + complete -F _docker 'docker-${name}' + ETC + + cat << 'BIN' > "$out/bin/docker-${name}" + exec ${config.package}/bin/docker --host '${socket}' "$@" + BIN + + chmod +x "$out/bin/docker-${name}" + ''; + }; + + daemon = { + debug = optional bool; + add-runtime = optional (listOf str); + allow-nondistributable-artifacts = optional (listOf str); + api-cors-header = optional str; + authorization-plugin = optional (listOf str); + bip = optional str; + bridge = optional str; + cgroup-parent = optional str; + containerd = optional str; + cpu-rt-period = optional int; + cpu-rt-runtime = optional int; + data-root = default "/docker/${name}" path; + default-gateway = optional str; + default-gateway-v6 = optional str; + default-runtime = optional str; + # TBD: default-ulimit = optional attributes + dns = optional (listOf str); + dns-opt = optional (listOf str); + dns-search = optional (listOf str); + exec-root = readonly "${config.daemon.data-root}/run" path; + experimental = optional bool; + fixed-cidr = optional str; + fixed-cidr-v6 = optional str; + group = default "docker-${name}" str; + hosts = readonly [socket] (listOf str); + icc = optional bool; + init = optional bool; + init-path = optional path; + insecure-registry = optional (listOf str); + ip = optional str; + ip-forward = optional bool; + ip-masq = optional bool; + iptables = optional bool; + ipv6 = optional bool; + live-restore = optional bool; + log-driver = readonly "journald" str; + log-level = optional (enum ["debug" "info" "warn" "error" "fatal"]); + max-concurrent-downloads = optional int; + max-concurrent-uploads = optional int; + metrics-addr = optional str; + mtu = optional int; + no-new-privileges = optional bool; + oom-score-adjust = optional int; + pidfile = readonly "${config.daemon.exec-root}/dockerd.pid" path; + raw-logs = optional bool; + registry-mirror = optional (listOf str); + seccomp-profile = optional path; + selinux-enabled = optional bool; + shutdown-timeout = optional int; + storage-driver = optional (enum ["aufs" "devicemapper" "btrfs" "zfs" "overlay" "overlay2"]); + storage-opt = optional (listOf str); + swarm-default-advertise-addr = optional str; + userland-proxy = optional bool; + userland-proxy-path = optional path; + userns-remap = optional str; + }; + }; +} |