Release NixOS 23.11
[NixPkgs.git] / nixos / modules / virtualisation / docker.nix
blob6fe460316091b454f20e152c46f4a965b88d6186
1 # Systemd services for docker.
3 { config, lib, pkgs, ... }:
5 with lib;
7 let
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;
16   ###### interface
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       };
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       };
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       };
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       };
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       };
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       };
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       };
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       };
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       };
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       };
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       };
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     };
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     };
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   };
172   ###### implementation
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 ];
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         };
205         path = [ pkgs.kmod ] ++ optional (cfg.storageDriver == "zfs") pkgs.zfs
206           ++ optional cfg.enableNvidia pkgs.nvidia-docker
207           ++ cfg.extraPackages;
208       };
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       };
221       systemd.services.docker-prune = {
222         description = "Prune docker resources";
224         restartIfChanged = false;
225         unitConfig.X-StopOnRemoval = false;
227         serviceConfig.Type = "oneshot";
229         script = ''
230           ${cfg.package}/bin/docker system prune -f ${toString cfg.autoPrune.flags}
231         '';
233         startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates;
234         after = [ "docker.service" ];
235         requires = [ "docker.service" ];
236       };
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         }];
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   ]);
258   imports = [
259     (mkRemovedOptionModule ["virtualisation" "docker" "socketActivation"] "This option was removed and socket activation is now always active")
260   ];