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 = true;
35 description =
36 ''
37 This option enables docker with socket activation. I.e. docker will
38 start when first called by client.
39 '';
40 };
41 storageDriver =
42 mkOption {
43 type = types.enum ["aufs" "btrfs" "devicemapper" "overlay" "zfs"];
44 default = "devicemapper";
45 description =
46 ''
47 This option determines which Docker storage driver to use.
48 '';
49 };
50 extraOptions =
51 mkOption {
52 type = types.separatedString " ";
53 default = "";
54 description =
55 ''
56 The extra command-line options to pass to
57 <command>docker</command> daemon.
58 '';
59 };
60
61 postStart =
62 mkOption {
63 type = types.lines;
64 default = ''
65 while ! [ -e /var/run/docker.sock ]; do
66 sleep 0.1
67 done
68 '';
69 description = ''
70 The postStart phase of the systemd service. You may need to
71 override this if you are passing in flags to docker which
72 don't cause the socket file to be created. This option is ignored
73 if socket activation is used.
74 '';
75 };
76
77
78 };
79
80 ###### implementation
81
82 config = mkIf cfg.enable (mkMerge [
83 { environment.systemPackages = [ pkgs.docker ];
84 users.extraGroups.docker.gid = config.ids.gids.docker;
85 systemd.services.docker = {
86 description = "Docker Application Container Engine";
87 wantedBy = optional (!cfg.socketActivation) "multi-user.target";
88 after = [ "network.target" ] ++ (optional cfg.socketActivation "docker.socket") ;
89 requires = optional cfg.socketActivation "docker.socket";
90 serviceConfig = {
91 ExecStart = "${pkgs.docker}/bin/docker daemon --group=docker --storage-driver=${cfg.storageDriver} ${optionalString cfg.socketActivation "--host=fd://"} ${cfg.extraOptions}";
92 # I'm not sure if that limits aren't too high, but it's what
93 # goes in config bundled with docker itself
94 LimitNOFILE = 1048576;
95 LimitNPROC = 1048576;
96 } // proxy_env;
97
98 path = [ pkgs.kmod ] ++ (optional (cfg.storageDriver == "zfs") pkgs.zfs);
99
100 postStart = if cfg.socketActivation then "" else cfg.postStart;
101
102 # Presumably some containers are running we don't want to interrupt
103 restartIfChanged = false;
104 };
105 }
106 (mkIf cfg.socketActivation {
107 systemd.sockets.docker = {
108 description = "Docker Socket for the API";
109 wantedBy = [ "sockets.target" ];
110 socketConfig = {
111 ListenStream = "/var/run/docker.sock";
112 SocketMode = "0660";
113 SocketUser = "root";
114 SocketGroup = "docker";
115 };
116 };
117 })
118 ]);
119
120}