at 23.11-pre 7.5 kB view raw
1# Systemd services for docker. 2 3{ config, lib, pkgs, ... }: 4 5with lib; 6 7let 8 9 cfg = config.virtualisation.docker; 10 proxy_env = config.networking.proxy.envVars; 11 settingsFormat = pkgs.formats.json {}; 12 daemonSettingsFile = settingsFormat.generate "daemon.json" cfg.daemon.settings; 13in 14 15{ 16 ###### interface 17 18 options.virtualisation.docker = { 19 enable = 20 mkOption { 21 type = types.bool; 22 default = false; 23 description = 24 lib.mdDoc '' 25 This option enables docker, a daemon that manages 26 linux containers. Users in the "docker" group can interact with 27 the daemon (e.g. to start or stop containers) using the 28 {command}`docker` command line tool. 29 ''; 30 }; 31 32 listenOptions = 33 mkOption { 34 type = types.listOf types.str; 35 default = ["/run/docker.sock"]; 36 description = 37 lib.mdDoc '' 38 A list of unix and tcp docker should listen to. The format follows 39 ListenStream as described in systemd.socket(5). 40 ''; 41 }; 42 43 enableOnBoot = 44 mkOption { 45 type = types.bool; 46 default = true; 47 description = 48 lib.mdDoc '' 49 When enabled dockerd is started on boot. This is required for 50 containers which are created with the 51 `--restart=always` flag to work. If this option is 52 disabled, docker might be started on demand by socket activation. 53 ''; 54 }; 55 56 daemon.settings = 57 mkOption { 58 type = settingsFormat.type; 59 default = { }; 60 example = { 61 ipv6 = true; 62 "fixed-cidr-v6" = "fd00::/80"; 63 }; 64 description = lib.mdDoc '' 65 Configuration for docker daemon. The attributes are serialized to JSON used as daemon.conf. 66 See https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file 67 ''; 68 }; 69 70 enableNvidia = 71 mkOption { 72 type = types.bool; 73 default = false; 74 description = lib.mdDoc '' 75 Enable nvidia-docker wrapper, supporting NVIDIA GPUs inside docker containers. 76 ''; 77 }; 78 79 liveRestore = 80 mkOption { 81 type = types.bool; 82 default = true; 83 description = 84 lib.mdDoc '' 85 Allow dockerd to be restarted without affecting running container. 86 This option is incompatible with docker swarm. 87 ''; 88 }; 89 90 storageDriver = 91 mkOption { 92 type = types.nullOr (types.enum ["aufs" "btrfs" "devicemapper" "overlay" "overlay2" "zfs"]); 93 default = null; 94 description = 95 lib.mdDoc '' 96 This option determines which Docker storage driver to use. By default 97 it let's docker automatically choose preferred storage driver. 98 ''; 99 }; 100 101 logDriver = 102 mkOption { 103 type = types.enum ["none" "json-file" "syslog" "journald" "gelf" "fluentd" "awslogs" "splunk" "etwlogs" "gcplogs" "local"]; 104 default = "journald"; 105 description = 106 lib.mdDoc '' 107 This option determines which Docker log driver to use. 108 ''; 109 }; 110 111 extraOptions = 112 mkOption { 113 type = types.separatedString " "; 114 default = ""; 115 description = 116 lib.mdDoc '' 117 The extra command-line options to pass to 118 {command}`docker` daemon. 119 ''; 120 }; 121 122 autoPrune = { 123 enable = mkOption { 124 type = types.bool; 125 default = false; 126 description = lib.mdDoc '' 127 Whether to periodically prune Docker resources. If enabled, a 128 systemd timer will run `docker system prune -f` 129 as specified by the `dates` option. 130 ''; 131 }; 132 133 flags = mkOption { 134 type = types.listOf types.str; 135 default = []; 136 example = [ "--all" ]; 137 description = lib.mdDoc '' 138 Any additional flags passed to {command}`docker system prune`. 139 ''; 140 }; 141 142 dates = mkOption { 143 default = "weekly"; 144 type = types.str; 145 description = lib.mdDoc '' 146 Specification (in the format described by 147 {manpage}`systemd.time(7)`) of the time at 148 which the prune will occur. 149 ''; 150 }; 151 }; 152 153 package = mkOption { 154 default = pkgs.docker; 155 defaultText = literalExpression "pkgs.docker"; 156 type = types.package; 157 description = lib.mdDoc '' 158 Docker package to be used in the module. 159 ''; 160 }; 161 }; 162 163 ###### implementation 164 165 config = mkIf cfg.enable (mkMerge [{ 166 boot.kernelModules = [ "bridge" "veth" "br_netfilter" "xt_nat" ]; 167 boot.kernel.sysctl = { 168 "net.ipv4.conf.all.forwarding" = mkOverride 98 true; 169 "net.ipv4.conf.default.forwarding" = mkOverride 98 true; 170 }; 171 environment.systemPackages = [ cfg.package ] 172 ++ optional cfg.enableNvidia pkgs.nvidia-docker; 173 users.groups.docker.gid = config.ids.gids.docker; 174 systemd.packages = [ cfg.package ]; 175 176 systemd.services.docker = { 177 wantedBy = optional cfg.enableOnBoot "multi-user.target"; 178 after = [ "network.target" "docker.socket" ]; 179 requires = [ "docker.socket" ]; 180 environment = proxy_env; 181 serviceConfig = { 182 Type = "notify"; 183 ExecStart = [ 184 "" 185 '' 186 ${cfg.package}/bin/dockerd \ 187 --config-file=${daemonSettingsFile} \ 188 ${cfg.extraOptions} 189 '']; 190 ExecReload=[ 191 "" 192 "${pkgs.procps}/bin/kill -s HUP $MAINPID" 193 ]; 194 }; 195 196 path = [ pkgs.kmod ] ++ optional (cfg.storageDriver == "zfs") pkgs.zfs 197 ++ optional cfg.enableNvidia pkgs.nvidia-docker; 198 }; 199 200 systemd.sockets.docker = { 201 description = "Docker Socket for the API"; 202 wantedBy = [ "sockets.target" ]; 203 socketConfig = { 204 ListenStream = cfg.listenOptions; 205 SocketMode = "0660"; 206 SocketUser = "root"; 207 SocketGroup = "docker"; 208 }; 209 }; 210 211 systemd.services.docker-prune = { 212 description = "Prune docker resources"; 213 214 restartIfChanged = false; 215 unitConfig.X-StopOnRemoval = false; 216 217 serviceConfig.Type = "oneshot"; 218 219 script = '' 220 ${cfg.package}/bin/docker system prune -f ${toString cfg.autoPrune.flags} 221 ''; 222 223 startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates; 224 after = [ "docker.service" ]; 225 requires = [ "docker.service" ]; 226 }; 227 228 assertions = [ 229 { assertion = cfg.enableNvidia -> config.hardware.opengl.driSupport32Bit or false; 230 message = "Option enableNvidia requires 32bit support libraries"; 231 }]; 232 233 virtualisation.docker.daemon.settings = { 234 group = "docker"; 235 hosts = [ "fd://" ]; 236 log-driver = mkDefault cfg.logDriver; 237 storage-driver = mkIf (cfg.storageDriver != null) (mkDefault cfg.storageDriver); 238 live-restore = mkDefault cfg.liveRestore; 239 runtimes = mkIf cfg.enableNvidia { 240 nvidia = { 241 path = "${pkgs.nvidia-docker}/bin/nvidia-container-runtime"; 242 }; 243 }; 244 }; 245 } 246 ]); 247 248 imports = [ 249 (mkRemovedOptionModule ["virtualisation" "docker" "socketActivation"] "This option was removed and socket activation is now always active") 250 ]; 251 252}