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 environment.MODULE_DIR = "/run/current-system/kernel-modules/lib/modules";
100
101 postStart = if cfg.socketActivation then "" else cfg.postStart;
102
103 # Presumably some containers are running we don't want to interrupt
104 restartIfChanged = false;
105 };
106 }
107 (mkIf cfg.socketActivation {
108 systemd.sockets.docker = {
109 description = "Docker Socket for the API";
110 wantedBy = [ "sockets.target" ];
111 socketConfig = {
112 ListenStream = "/var/run/docker.sock";
113 SocketMode = "0660";
114 SocketUser = "root";
115 SocketGroup = "docker";
116 };
117 };
118 })
119 ]);
120
121}