1# Systemd services for docker.
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8
9 cfg = config.virtualisation.docker;
10 pro = config.networking.proxy.default;
11 proxy_env = optionalAttrs (pro != null) { Environment = "\"http_proxy=${pro}\""; };
12
13in
14
15{
16 ###### interface
17
18 options.virtualisation.docker = {
19 enable =
20 mkOption {
21 type = types.bool;
22 default = false;
23 description =
24 ''
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> command line tool.
29 '';
30 };
31 socketActivation =
32 mkOption {
33 type = types.bool;
34 default = false;
35 description =
36 ''
37 This option enables docker with socket activation. I.e. docker will
38 start when first called by client.
39
40 Note: This is false by default because systemd lower than 214 that
41 nixos uses so far, doesn't support SocketGroup option, so socket
42 created by docker has root group now. This will likely be changed
43 in future. So set this option explicitly to false if you wish.
44 '';
45 };
46 extraOptions =
47 mkOption {
48 type = types.separatedString " ";
49 default = "";
50 description =
51 ''
52 The extra command-line options to pass to
53 <command>docker</command> daemon.
54 '';
55 };
56
57 postStart =
58 mkOption {
59 type = types.string;
60 default = ''
61 while ! [ -e /var/run/docker.sock ]; do
62 sleep 0.1
63 done
64 '';
65 description = ''
66 The postStart phase of the systemd service. You may need to
67 override this if you are passing in flags to docker which
68 don't cause the socket file to be created.
69 '';
70 };
71
72
73 };
74
75 ###### implementation
76
77 config = mkIf cfg.enable (mkMerge [
78 { environment.systemPackages = [ pkgs.docker ];
79 users.extraGroups.docker.gid = config.ids.gids.docker;
80 }
81 (mkIf cfg.socketActivation {
82
83 systemd.services.docker = {
84 description = "Docker Application Container Engine";
85 after = [ "network.target" "docker.socket" ];
86 requires = [ "docker.socket" ];
87 serviceConfig = {
88 ExecStart = "${pkgs.docker}/bin/docker --daemon=true --host=fd:// --group=docker ${cfg.extraOptions}";
89 # I'm not sure if that limits aren't too high, but it's what
90 # goes in config bundled with docker itself
91 LimitNOFILE = 1048576;
92 LimitNPROC = 1048576;
93 } // proxy_env;
94 };
95
96 systemd.sockets.docker = {
97 description = "Docker Socket for the API";
98 wantedBy = [ "sockets.target" ];
99 socketConfig = {
100 ListenStream = "/var/run/docker.sock";
101 SocketMode = "0660";
102 SocketUser = "root";
103 SocketGroup = "docker";
104 };
105 };
106 })
107 (mkIf (!cfg.socketActivation) {
108
109 systemd.services.docker = {
110 description = "Docker Application Container Engine";
111 wantedBy = [ "multi-user.target" ];
112 after = [ "network.target" ];
113 serviceConfig = {
114 ExecStart = "${pkgs.docker}/bin/docker --daemon=true --group=docker ${cfg.extraOptions}";
115 # I'm not sure if that limits aren't too high, but it's what
116 # goes in config bundled with docker itself
117 LimitNOFILE = 1048576;
118 LimitNPROC = 1048576;
119 } // proxy_env;
120
121 path = [ pkgs.kmod ];
122 environment.MODULE_DIR = "/run/current-system/kernel-modules/lib/modules";
123
124 postStart = cfg.postStart;
125
126 # Presumably some containers are running we don't want to interrupt
127 restartIfChanged = false;
128 };
129 })
130 ]);
131
132}