arion/src/nix/modules/service/docker-compose-service.nix

400 lines
12 KiB
Nix
Raw Normal View History

/*
2019-10-03 21:30:14 +02:00
This service-level module defines the out.service option, using
the user-facing options service.image, service.volumes, etc.
*/
{ pkgs, lib, config, options, ... }:
let
inherit (lib) mkOption types;
inherit (types) listOf nullOr attrsOf str either int bool submodule enum;
2019-03-03 23:42:40 +01:00
inherit (import ../../lib.nix { inherit lib; })
link
2023-07-19 15:50:08 +02:00
serviceRef
;
2019-03-11 14:36:18 +01:00
cap_add = lib.attrNames (lib.filterAttrs (name: value: value == true) config.service.capabilities);
cap_drop = lib.attrNames (lib.filterAttrs (name: value: value == false) config.service.capabilities);
in
{
2019-10-03 21:30:14 +02:00
imports = [
(lib.mkRenamedOptionModule ["build" "service"] ["out" "service"])
];
options = {
2019-10-03 21:30:14 +02:00
out.service = mkOption {
2019-03-04 00:13:57 +01:00
type = attrsOf types.unspecified;
description = ''
2019-10-29 12:52:00 +01:00
Raw input for the service in `docker-compose.yaml`.
2019-03-04 00:13:57 +01:00
You should not need to use this option. If anything is
missing, please contribute the missing option.
This option is user accessible because it may serve as an
escape hatch for some.
'';
2019-10-03 21:30:14 +02:00
apply = config.assertWarn;
2019-03-04 00:13:57 +01:00
};
service.name = mkOption {
type = str;
description = ''
2019-10-29 12:52:00 +01:00
The name of the service - `<name>` in the composition-level `services.<name>`
'';
readOnly = true;
};
service.volumes = mkOption {
type = listOf types.unspecified;
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "volumes";
};
service.tmpfs = mkOption {
type = listOf types.str;
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "tmpfs";
};
service.build.context = mkOption {
2019-03-04 00:12:01 +01:00
type = nullOr str;
default = null;
2019-03-03 23:42:40 +01:00
description = ''
Locates a Dockerfile to use for creating an image to use in this service.
2023-07-19 15:50:08 +02:00
https://docs.docker.com/compose/compose-file/build/#context
2019-03-03 23:42:40 +01:00
'';
};
service.hostname = mkOption {
2019-03-04 00:12:01 +01:00
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = ''
${serviceRef "hostname"}
'';
};
service.tty = mkOption {
type = nullOr bool;
default = null;
2023-07-19 15:50:08 +02:00
description = ''
${serviceRef "tty"}
'';
};
service.environment = mkOption {
2019-03-04 00:12:01 +01:00
type = attrsOf (either str int);
default = {};
2023-07-19 15:50:08 +02:00
description = serviceRef "environment";
};
service.image = mkOption {
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = serviceRef "image";
};
service.command = mkOption {
type = nullOr types.unspecified;
default = null;
2023-07-19 15:50:08 +02:00
description = serviceRef "command";
};
service.container_name = mkOption {
type = nullOr types.str;
default = null;
2023-07-19 15:50:08 +02:00
description = serviceRef "container_name";
};
service.depends_on =
let conditionsModule = {
options = {
condition = mkOption {
type = enum ["service_started" "service_healthy" "service_completed_successfully"];
2023-07-19 15:50:08 +02:00
description = serviceRef "depends_on";
default = "service_started";
};
};
};
in mkOption {
type = either (listOf str) (attrsOf (submodule conditionsModule));
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "depends_on";
};
service.healthcheck = mkOption {
2023-07-19 15:50:08 +02:00
description = serviceRef "healthcheck";
type = submodule ({ config, options, ...}: {
options = {
_out = mkOption {
internal = true;
default = lib.optionalAttrs (options.test.highestPrio < 1500) {
inherit (config) test interval timeout start_period retries;
};
};
test = mkOption {
type = nullOr (listOf str);
default = null;
example = [ "CMD" "pg_isready" ];
2023-07-19 15:50:08 +02:00
description = serviceRef "healthcheck";
};
interval = mkOption {
type = str;
default = "30s";
example = "1m";
2023-07-19 15:50:08 +02:00
description = serviceRef "healthcheck";
};
timeout = mkOption {
type = str;
default = "30s";
example = "10s";
2023-07-19 15:50:08 +02:00
description = serviceRef "healthcheck";
};
start_period = mkOption {
type = str;
default = "0s";
example = "30s";
2023-07-19 15:50:08 +02:00
description = serviceRef "healthcheck";
};
retries = mkOption {
type = int;
default = 3;
2023-07-19 15:50:08 +02:00
description = serviceRef "healthcheck";
};
};
});
};
2019-03-11 14:36:49 +01:00
service.devices = mkOption {
type = listOf str;
default = [];
description = ''
See ${link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
2019-10-29 12:52:00 +01:00
"`docker run --device` documentation"}
2019-03-11 14:36:49 +01:00
2023-07-19 15:50:08 +02:00
${serviceRef "devices"}
2019-03-11 14:36:49 +01:00
'';
};
2021-04-10 00:51:40 +01:00
service.dns = mkOption {
type = listOf str;
default = [];
example = [ "8.8.8.8" "8.8.4.4" ];
2023-07-19 15:50:08 +02:00
description = serviceRef "dns";
2021-04-10 00:51:40 +01:00
};
2021-01-20 18:11:52 +01:00
service.labels = mkOption {
type = attrsOf str;
default = {};
2021-01-22 10:35:57 +01:00
example = {
"com.example.foo" = "bar";
"traefik.enable" = "true";
"traefik.http.routers.my-service.rule" = "Host(`my-service.localhost`)";
"traefik.http.routers.my-service.entrypoints" = "web";
};
2023-07-19 15:50:08 +02:00
description = serviceRef "labels";
2021-01-20 18:11:52 +01:00
};
service.links = mkOption {
2019-03-04 00:12:01 +01:00
type = listOf str;
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "links";
};
service.external_links = mkOption {
2019-03-04 00:12:01 +01:00
type = listOf str;
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "external_links";
};
service.extra_hosts = mkOption {
2019-03-04 00:12:01 +01:00
type = listOf str;
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "extra_hosts";
};
service.working_dir = mkOption {
2019-03-04 00:12:01 +01:00
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = ''
${serviceRef "working_dir"}
'';
};
service.privileged = mkOption {
type = nullOr bool;
default = null;
2023-07-19 15:50:08 +02:00
description = ''
${serviceRef "privileged"}
'';
};
service.entrypoint = mkOption {
2019-03-04 00:12:01 +01:00
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = serviceRef "entrypoint";
};
service.restart = mkOption {
2019-03-04 00:12:01 +01:00
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = serviceRef "restart";
};
2019-05-07 14:14:49 +07:00
service.user = mkOption {
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = ''
${serviceRef "user"}
'';
2019-05-07 14:14:49 +07:00
};
service.ports = mkOption {
type = listOf types.unspecified;
default = [];
description = ''
Expose ports on host. "host:container" or structured.
2019-03-03 23:42:40 +01:00
2023-07-19 15:50:08 +02:00
${serviceRef "ports"}
'';
};
service.expose = mkOption {
2019-03-04 00:12:01 +01:00
type = listOf str;
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "expose";
};
service.env_file = mkOption {
type = listOf str;
default = [];
2023-07-19 15:50:08 +02:00
description = serviceRef "env_file";
};
service.network_mode = mkOption {
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = serviceRef "network_mode";
};
2023-07-19 18:12:42 +09:00
service.networks =
let
networksModule = submodule ({ config, options, ...}: {
options = {
_out = mkOption {
internal = true;
readOnly = true;
default = lib.mapAttrs (k: opt: opt.value) (lib.filterAttrs (_: opt: opt.isDefined) { inherit (options) aliases ipv4_address ipv6_address link_local_ips priority; });
2023-07-19 18:12:42 +09:00
};
aliases = mkOption {
type = listOf str;
description = serviceRef "aliases";
default = [ ];
};
ipv4_address = mkOption {
type = str;
description = serviceRef "ipv4_address-ipv6_address";
};
ipv6_address = mkOption {
type = str;
description = serviceRef "ipv4_address-ipv6_address";
};
link_local_ips = mkOption {
type = listOf str;
description = serviceRef "link_local_ips";
};
priority = mkOption {
type = int;
description = serviceRef "priority";
};
2023-07-19 18:12:42 +09:00
};
});
in
mkOption {
type = either (listOf str) (attrsOf networksModule);
default = [];
description = serviceRef "networks";
};
service.stop_signal = mkOption {
type = nullOr str;
default = null;
2023-07-19 15:50:08 +02:00
description = serviceRef "stop_signal";
};
2023-11-06 21:58:30 -08:00
service.stop_grace_period = mkOption {
type = nullOr str;
default = null;
description = serviceRef "stop_grace_period";
};
2019-05-07 15:33:24 +07:00
service.sysctls = mkOption {
type = attrsOf (either str int);
default = {};
2023-07-19 15:50:08 +02:00
description = serviceRef "sysctls";
2019-05-07 15:33:24 +07:00
};
2019-03-11 14:36:18 +01:00
service.capabilities = mkOption {
type = attrsOf (nullOr bool);
default = {};
example = { ALL = true; SYS_ADMIN = false; NET_ADMIN = false; };
description = ''
Enable/disable linux capabilities, or pick Docker's default.
2019-10-29 12:52:00 +01:00
Setting a capability to `true` means that it will be
"added". Setting it to `false` means that it will be "dropped".
2019-03-11 14:36:18 +01:00
2019-10-29 12:52:00 +01:00
Omitted and `null` capabilities will therefore be set
2019-03-11 14:36:18 +01:00
according to Docker's ${
link "https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities"
"default list of capabilities."
}
2023-07-19 15:50:08 +02:00
${serviceRef "cap_add"}
${serviceRef "cap_drop"}
2019-03-11 14:36:18 +01:00
'';
};
};
2019-10-03 21:30:14 +02:00
config.out.service = {
inherit (config.service)
volumes
environment
2019-05-07 15:33:24 +07:00
sysctls
;
} // lib.optionalAttrs (config.service.image != null) {
inherit (config.service) image;
} // lib.optionalAttrs (config.service.build.context != null) {
inherit (config.service) build;
2019-03-11 14:36:18 +01:00
} // lib.optionalAttrs (cap_add != []) {
inherit cap_add;
} // lib.optionalAttrs (cap_drop != []) {
inherit cap_drop;
} // lib.optionalAttrs (config.service.command != null) {
inherit (config.service) command;
} // lib.optionalAttrs (config.service.container_name != null) {
inherit (config.service) container_name;
} // lib.optionalAttrs (config.service.depends_on != []) {
inherit (config.service) depends_on;
} // lib.optionalAttrs (options.service.healthcheck.highestPrio < 1500) {
healthcheck = config.service.healthcheck._out;
2019-03-11 14:36:49 +01:00
} // lib.optionalAttrs (config.service.devices != []) {
inherit (config.service) devices;
} // lib.optionalAttrs (config.service.entrypoint != null) {
inherit (config.service) entrypoint;
} // lib.optionalAttrs (config.service.env_file != []) {
inherit (config.service) env_file;
} // lib.optionalAttrs (config.service.expose != []) {
inherit (config.service) expose;
} // lib.optionalAttrs (config.service.external_links != []) {
inherit (config.service) external_links;
} // lib.optionalAttrs (config.service.extra_hosts != []) {
inherit (config.service) extra_hosts;
} // lib.optionalAttrs (config.service.hostname != null) {
inherit (config.service) hostname;
2021-04-10 00:51:40 +01:00
} // lib.optionalAttrs (config.service.dns != []) {
inherit (config.service) dns;
2021-01-20 18:11:52 +01:00
} // lib.optionalAttrs (config.service.labels != {}) {
inherit (config.service) labels;
} // lib.optionalAttrs (config.service.links != []) {
inherit (config.service) links;
} // lib.optionalAttrs (config.service.ports != []) {
inherit (config.service) ports;
} // lib.optionalAttrs (config.service.privileged != null) {
inherit (config.service) privileged;
} // lib.optionalAttrs (config.service.network_mode != null) {
inherit (config.service) network_mode;
2023-07-19 18:12:42 +09:00
} // lib.optionalAttrs (config.service.networks != [] && config.service.networks != {}) {
networks =
if (builtins.isAttrs config.service.networks) then builtins.mapAttrs (_: v: v._out) config.service.networks
else config.service.networks;
} // lib.optionalAttrs (config.service.restart != null) {
inherit (config.service) restart;
} // lib.optionalAttrs (config.service.stop_signal != null) {
inherit (config.service) stop_signal;
2023-11-06 21:58:30 -08:00
} // lib.optionalAttrs (config.service.stop_grace_period != null) {
inherit (config.service) stop_grace_period;
} // lib.optionalAttrs (config.service.tmpfs != []) {
inherit (config.service) tmpfs;
} // lib.optionalAttrs (config.service.tty != null) {
inherit (config.service) tty;
} // lib.optionalAttrs (config.service.working_dir != null) {
inherit (config.service) working_dir;
2019-05-07 14:14:49 +07:00
} // lib.optionalAttrs (config.service.user != null) {
inherit (config.service) user;
};
}