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