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}