at 24.05-pre 7.8 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 extraPackages = mkOption { 163 type = types.listOf types.package; 164 default = [ ]; 165 example = literalExpression "with pkgs; [ criu ]"; 166 description = lib.mdDoc '' 167 Extra packages to add to PATH for the docker daemon process. 168 ''; 169 }; 170 }; 171 172 ###### implementation 173 174 config = mkIf cfg.enable (mkMerge [{ 175 boot.kernelModules = [ "bridge" "veth" "br_netfilter" "xt_nat" ]; 176 boot.kernel.sysctl = { 177 "net.ipv4.conf.all.forwarding" = mkOverride 98 true; 178 "net.ipv4.conf.default.forwarding" = mkOverride 98 true; 179 }; 180 environment.systemPackages = [ cfg.package ] 181 ++ optional cfg.enableNvidia pkgs.nvidia-docker; 182 users.groups.docker.gid = config.ids.gids.docker; 183 systemd.packages = [ cfg.package ]; 184 185 systemd.services.docker = { 186 wantedBy = optional cfg.enableOnBoot "multi-user.target"; 187 after = [ "network.target" "docker.socket" ]; 188 requires = [ "docker.socket" ]; 189 environment = proxy_env; 190 serviceConfig = { 191 Type = "notify"; 192 ExecStart = [ 193 "" 194 '' 195 ${cfg.package}/bin/dockerd \ 196 --config-file=${daemonSettingsFile} \ 197 ${cfg.extraOptions} 198 '']; 199 ExecReload=[ 200 "" 201 "${pkgs.procps}/bin/kill -s HUP $MAINPID" 202 ]; 203 }; 204 205 path = [ pkgs.kmod ] ++ optional (cfg.storageDriver == "zfs") pkgs.zfs 206 ++ optional cfg.enableNvidia pkgs.nvidia-docker 207 ++ cfg.extraPackages; 208 }; 209 210 systemd.sockets.docker = { 211 description = "Docker Socket for the API"; 212 wantedBy = [ "sockets.target" ]; 213 socketConfig = { 214 ListenStream = cfg.listenOptions; 215 SocketMode = "0660"; 216 SocketUser = "root"; 217 SocketGroup = "docker"; 218 }; 219 }; 220 221 systemd.services.docker-prune = { 222 description = "Prune docker resources"; 223 224 restartIfChanged = false; 225 unitConfig.X-StopOnRemoval = false; 226 227 serviceConfig.Type = "oneshot"; 228 229 script = '' 230 ${cfg.package}/bin/docker system prune -f ${toString cfg.autoPrune.flags} 231 ''; 232 233 startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates; 234 after = [ "docker.service" ]; 235 requires = [ "docker.service" ]; 236 }; 237 238 assertions = [ 239 { assertion = cfg.enableNvidia && pkgs.stdenv.isx86_64 -> config.hardware.opengl.driSupport32Bit or false; 240 message = "Option enableNvidia on x86_64 requires 32bit support libraries"; 241 }]; 242 243 virtualisation.docker.daemon.settings = { 244 group = "docker"; 245 hosts = [ "fd://" ]; 246 log-driver = mkDefault cfg.logDriver; 247 storage-driver = mkIf (cfg.storageDriver != null) (mkDefault cfg.storageDriver); 248 live-restore = mkDefault cfg.liveRestore; 249 runtimes = mkIf cfg.enableNvidia { 250 nvidia = { 251 path = "${pkgs.nvidia-docker}/bin/nvidia-container-runtime"; 252 }; 253 }; 254 }; 255 } 256 ]); 257 258 imports = [ 259 (mkRemovedOptionModule ["virtualisation" "docker" "socketActivation"] "This option was removed and socket activation is now always active") 260 ]; 261 262}