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
12in
13
14{
15 ###### interface
16
17 options.virtualisation.docker = {
18 enable =
19 mkOption {
20 type = types.bool;
21 default = false;
22 description =
23 ''
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> command line tool.
28 '';
29 };
30
31 listenOptions =
32 mkOption {
33 type = types.listOf types.str;
34 default = ["/var/run/docker.sock"];
35 description =
36 ''
37 A list of unix and tcp docker should listen to. The format follows
38 ListenStream as described in systemd.socket(5).
39 '';
40 };
41
42 enableOnBoot =
43 mkOption {
44 type = types.bool;
45 default = true;
46 description =
47 ''
48 When enabled dockerd is started on boot. This is required for
49 container, which are created with the
50 <literal>--restart=always</literal> flag, to work. If this option is
51 disabled, docker might be started on demand by socket activation.
52 '';
53 };
54
55 liveRestore =
56 mkOption {
57 type = types.bool;
58 default = true;
59 description =
60 ''
61 Allow dockerd to be restarted without affecting running container.
62 This option is incompatible with docker swarm.
63 '';
64 };
65
66 storageDriver =
67 mkOption {
68 type = types.nullOr (types.enum ["aufs" "btrfs" "devicemapper" "overlay" "overlay2" "zfs"]);
69 default = null;
70 description =
71 ''
72 This option determines which Docker storage driver to use. By default
73 it let's docker automatically choose preferred storage driver.
74 '';
75 };
76
77 logDriver =
78 mkOption {
79 type = types.enum ["none" "json-file" "syslog" "journald" "gelf" "fluentd" "awslogs" "splunk" "etwlogs" "gcplogs"];
80 default = "journald";
81 description =
82 ''
83 This option determines which Docker log driver to use.
84 '';
85 };
86
87 extraOptions =
88 mkOption {
89 type = types.separatedString " ";
90 default = "";
91 description =
92 ''
93 The extra command-line options to pass to
94 <command>docker</command> daemon.
95 '';
96 };
97
98 autoPrune = {
99 enable = mkOption {
100 type = types.bool;
101 default = false;
102 description = ''
103 Whether to periodically prune Docker resources. If enabled, a
104 systemd timer will run <literal>docker system prune -f</literal>
105 as specified by the <literal>dates</literal> option.
106 '';
107 };
108
109 flags = mkOption {
110 type = types.listOf types.str;
111 default = [];
112 example = [ "--all" ];
113 description = ''
114 Any additional flags passed to <command>docker system prune</command>.
115 '';
116 };
117
118 dates = mkOption {
119 default = "weekly";
120 type = types.str;
121 description = ''
122 Specification (in the format described by
123 <citerefentry><refentrytitle>systemd.time</refentrytitle>
124 <manvolnum>7</manvolnum></citerefentry>) of the time at
125 which the prune will occur.
126 '';
127 };
128 };
129
130 package = mkOption {
131 default = pkgs.docker;
132 type = types.package;
133 example = pkgs.docker-edge;
134 description = ''
135 Docker package to be used in the module.
136 '';
137 };
138 };
139
140 ###### implementation
141
142 config = mkIf cfg.enable (mkMerge [{
143 environment.systemPackages = [ cfg.package ];
144 users.groups.docker.gid = config.ids.gids.docker;
145 systemd.packages = [ cfg.package ];
146
147 systemd.services.docker = {
148 wantedBy = optional cfg.enableOnBoot "multi-user.target";
149 environment = proxy_env;
150 serviceConfig = {
151 ExecStart = [
152 ""
153 ''
154 ${cfg.package}/bin/dockerd \
155 --group=docker \
156 --host=fd:// \
157 --log-driver=${cfg.logDriver} \
158 ${optionalString (cfg.storageDriver != null) "--storage-driver=${cfg.storageDriver}"} \
159 ${optionalString cfg.liveRestore "--live-restore" } \
160 ${cfg.extraOptions}
161 ''];
162 ExecReload=[
163 ""
164 "${pkgs.procps}/bin/kill -s HUP $MAINPID"
165 ];
166 };
167
168 path = [ pkgs.kmod ] ++ (optional (cfg.storageDriver == "zfs") pkgs.zfs);
169 };
170
171 systemd.sockets.docker = {
172 description = "Docker Socket for the API";
173 wantedBy = [ "sockets.target" ];
174 socketConfig = {
175 ListenStream = cfg.listenOptions;
176 SocketMode = "0660";
177 SocketUser = "root";
178 SocketGroup = "docker";
179 };
180 };
181
182
183 systemd.services.docker-prune = {
184 description = "Prune docker resources";
185
186 restartIfChanged = false;
187 unitConfig.X-StopOnRemoval = false;
188
189 serviceConfig.Type = "oneshot";
190
191 script = ''
192 ${cfg.package}/bin/docker system prune -f ${toString cfg.autoPrune.flags}
193 '';
194
195 startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates;
196 };
197 }
198 ]);
199
200 imports = [
201 (mkRemovedOptionModule ["virtualisation" "docker" "socketActivation"] "This option was removed in favor of starting docker at boot")
202 ];
203
204}