diff --git a/zabbix_conf/docker.conf b/zabbix_conf/docker.conf new file mode 100644 index 0000000..7002a1a --- /dev/null +++ b/zabbix_conf/docker.conf @@ -0,0 +1,9 @@ +# Discover Docker items +# $1 can be containers, networks, volumes +UserParameter=container.docker.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_docker_sudo --what $1 + +# Type: Agent or Agent (active) +# container.docker.check.all[type,id] +# Where type is what to monitor (global, container, network, volume) +# id is the id of the item to monitor. Can be a name or an ID. For the global check, there's no ID +UserParameter=container.docker.check[*],/usr/bin/sudo /var/lib/zabbix/bin/check_docker_sudo --$1 $2 diff --git a/zabbix_scripts/check_docker_sudo b/zabbix_scripts/check_docker_sudo new file mode 100755 index 0000000..160f53f --- /dev/null +++ b/zabbix_scripts/check_docker_sudo @@ -0,0 +1,90 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use JSON; +use Getopt::Long; +use File::Which; +use Date::Parse; + +my $docker = which('docker'); +my $json = {}; +my $pretty = 0; +my ($global, $container, $network, $volume) = undef; + +GetOptions( + 'global' => \$global, + 'container=s' => \$container, + 'network=s' => \$network, + 'volume=s' => \$volume, + 'pretty' => \$pretty +); + +# Sanitize args +if (defined $container and not $container =~ m/^[a-zA-Z0-9\-_]+/){ + die "Invalid container ID $container\n"; +} elsif (defined $network and not $network =~ m/^[a-zA-Z0-9\-_]+/){ + die "Invalid network ID\n"; +} elsif (defined $volume and not $volume =~ m/^[a-zA-Z0-9\-_]+/){ + die "Invalid volume name\n"; +} + +# Default formating +my $format = '{{ json . }}'; +my $cmd; +if ($global){ + $json->{info} = from_json(qx($docker info --format '$format')); +} elsif (defined $container) { + $json->{inspect} = from_json(qx($docker container inspect $container --format '$format')); + $json->{stats} = from_json(qx($docker container stats $container --format '$format' --no-stream)); + # Remove percent sign so Zabbix can get raw value + foreach my $stat (qw(MemPerc CPUPerc)){ + $json->{stats}->{$stat} =~ s/%$//; + } + # Extract mem usage vs mem limit, net in vs net out and blk read vs blk write + ($json->{stats}->{MemCurrent}, $json->{stats}->{MemLimit}) = split(/\s*\/\s*/, $json->{stats}->{MemUsage}); + ($json->{stats}->{NetIOIn}, $json->{stats}->{NetIOOut}) = split(/\s*\/\s*/, $json->{stats}->{NetIO}); + ($json->{stats}->{BlockIORead}, $json->{stats}->{BlockIOWrite}) = split(/\s*\/\s*/, $json->{stats}->{BlockIO}); + # Convert into Bytes + foreach my $stat (qw(MemCurrent MemLimit NetIOIn NetIOOut BlockIORead BlockIOWrite)){ + $json->{stats}->{$stat} = convert_unit($json->{stats}->{$stat}); + } + # Compute a useful Uptime from the StartedAt value + if ($json->{inspect}->{State}->{Running}){ + $json->{stats}->{Uptime} = int(time() - str2time($json->{inspect}->{State}->{StartedAt})); + } else { + $json->{stats}->{Uptime} = 0; + } +} elsif (defined $network){ + $json->{inspect} = from_json(qx($docker network inspect $network --format '$format')); +} elsif (defined $volume){ + $json->{inspect} = from_json(qx($docker volume inspect $volume --format '$format')); +} + +print to_json($json, { pretty => $pretty }) . "\n"; + + +sub convert_unit { + my $val = shift; + my $suffix_multiplier = { + ki => 1024, + Ki => 1024, + Mi => 1024 * 1024, + Gi => 1024 * 1024 * 1024, + Ti => 1024 * 1024 * 1024 * 1024, + Pi => 1024 * 1024 * 1024 * 1024 * 1024, + k => 1000, + K => 1000, + M => 1000 * 1000, + G => 1000 * 1000 * 1000, + T => 1000 * 1000 * 1000 * 1000, + P => 1000 * 1000 * 1000 * 1000 * 1000 + }; + if ($val =~ m/^(\d+(\.\d+)?)(Ki|Mi|Gi|Ti|Pi|K|M|G|T|P)?B/){ + $val = int($1 * $suffix_multiplier->{$3}) if (defined $3 and defined $suffix_multiplier->{$3}); + # Remove the Bytes suffix if remaining + $val =~ s/B$//; + } + return $val; +} + diff --git a/zabbix_scripts/disco_docker_sudo b/zabbix_scripts/disco_docker_sudo new file mode 100755 index 0000000..10bbac2 --- /dev/null +++ b/zabbix_scripts/disco_docker_sudo @@ -0,0 +1,68 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use JSON; +use Getopt::Long; +use File::Which; +use Data::Dumper; + +my $what = 'containers'; +my $pretty = 0; + +GetOptions( + 'what=s' => \$what, + 'pretty' => \$pretty +); + +my $json = []; + +my $docker = which('docker'); + +# If the docker cli is not available, terminate now +if (not defined $docker){ + print $json . "\n"; + exit(0); +} + +my $format; +my $cmd; +if ($what =~ m/^containers?/){ + $format = '{' . + '"{#DOCKER_CONTAINER_ID}":"{{ .ID }}",' . + '"{#DOCKER_CONTAINER_IMAGE}": "{{ .Image }}",' . + '"{#DOCKER_CONTAINER_NAME}":"{{ .Names }}",' . + '"{#DOCKER_CONTAINER_STATE}": "{{ .State }}"' . + '}'; + $cmd = "$docker container list --all --format '$format'"; +} elsif ($what =~ m/^networks?/){ + $format = '{' . + '"{#DOCKER_NET_ID}":"{{ .ID }}",' . + '"{#DOCKER_NET_NAME}":"{{ .Name }}",' . + '"{#DOCKER_NET_DRIVER}":"{{ .Driver }}",' . + '"{#DOCKER_NET_SCOPE}":"{{ .Scope }}"' . + '}'; + $cmd = "$docker network list --format '$format'"; +} elsif ($what =~ m/^volumes?/){ + $format = '{' . + '"{#DOCKER_VOL_NAME}":"{{ .Name }}",' . + '"{#DOCKER_VOL_DRIVER}":"{{ .Driver }}",' . + '"{#DOCKER_VOL_SCOPE}":"{{ .Scope }}"' . + '}'; + $cmd = "$docker volume list --format '$format'"; +} else { + print <<_EOF +Usage: $0 --what= [--pretty] +with available item being + * containers : list containers, including stopped ones + * networks : list networks + * volumes : list volumes +_EOF +} + +foreach my $line (qx($cmd)){ + chomp $line; + push @{$json}, from_json($line); +} +print to_json($json, { pretty => $pretty }) . "\n"; +exit(0); diff --git a/zabbix_templates/Template_App_Docker.yaml b/zabbix_templates/Template_App_Docker.yaml new file mode 100644 index 0000000..b004e36 --- /dev/null +++ b/zabbix_templates/Template_App_Docker.yaml @@ -0,0 +1,561 @@ +zabbix_export: + version: '5.4' + date: '2022-01-12T15:22:36Z' + groups: + - + uuid: 7df96b18c230490a9a0a9e2307226338 + name: Templates + templates: + - + uuid: 722c34dae28f471b992685f75b217e84 + template: Template_App_Docker + name: Template_App_Docker + groups: + - + name: Templates + items: + - + uuid: b35116a368e94b0698951010ddb496b5 + name: 'Docker: Number of paused container' + type: DEPENDENT + key: 'container.docker.check[global,ContainersPaused]' + delay: '0' + history: 30d + trends: 1095d + units: '!container(s)' + preprocessing: + - + type: JSONPATH + parameters: + - $.info.ContainersPaused + master_item: + key: 'container.docker.check[global]' + - + uuid: ff406b09a49f42ef80e004f7b8737c9b + name: 'Docker: Number of running container' + type: DEPENDENT + key: 'container.docker.check[global,ContainersRunning]' + delay: '0' + history: 30d + trends: 1095d + units: '!container(s)' + preprocessing: + - + type: JSONPATH + parameters: + - $.info.ContainersRunning + master_item: + key: 'container.docker.check[global]' + triggers: + - + uuid: 85e456243c714349b34ff6504d122004 + expression: 'change(/Template_App_Docker/container.docker.check[global,ContainersRunning])=1' + name: 'Number of running containers changed to {ITEM.LASTVALUE1}' + priority: INFO + - + uuid: 69c12d97c6604c608fba4d2c0d4875bb + name: 'Docker: Number of stopped container' + type: DEPENDENT + key: 'container.docker.check[global,ContainersStopped]' + delay: '0' + history: 30d + trends: 1095d + units: '!container(s)' + preprocessing: + - + type: JSONPATH + parameters: + - $.info.ContainersStopped + master_item: + key: 'container.docker.check[global]' + - + uuid: c6831879964a4a3a90fc82530e6a0d43 + name: 'Docker: Number of containers' + type: DEPENDENT + key: 'container.docker.check[global,Containers]' + delay: '0' + history: 30d + trends: 1095d + units: '!container(s)' + preprocessing: + - + type: JSONPATH + parameters: + - $.info.Containers + master_item: + key: 'container.docker.check[global]' + - + uuid: 1da51785c3d34faf8ba7ab17d0b46b38 + name: 'Docker: Live restore status' + type: DEPENDENT + key: 'container.docker.check[global,LiveRestoreEnabled]' + delay: '0' + history: 7d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.info.LiveRestoreEnabled + master_item: + key: 'container.docker.check[global]' + triggers: + - + uuid: 85a2fc38a6bb42e183de3d4687f466e8 + expression: 'last(/Template_App_Docker/container.docker.check[global,LiveRestoreEnabled])<>"true" and {$DOCKER_WARN_NO_LIVE_RESTORE}=1' + name: 'Docker live restore isn''t enabled' + priority: WARNING + - + uuid: ab2d3bd636964a21b764b2f33f2e109e + name: 'Docker: server version' + type: DEPENDENT + key: 'container.docker.check[global,ServerVersion]' + delay: '0' + history: 15d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.info.ServerVersion + master_item: + key: 'container.docker.check[global]' + triggers: + - + uuid: 8c535ff0d73240c395226ee91a8096c4 + expression: '(last(/Template_App_Docker/container.docker.check[global,ServerVersion])<>last(/Template_App_Docker/container.docker.check[global,ServerVersion],#6))=1' + name: 'Docker version changed ({ITEM.LASTVALUE1})' + priority: WARNING + - + uuid: d5c424dc767c4a5ea1ee441e76770411 + name: 'Docker global info' + key: 'container.docker.check[global]' + history: '0' + trends: '0' + value_type: TEXT + discovery_rules: + - + uuid: e459f638e15f495db3e4a9060e60f7c8 + name: 'Docker: container discovery' + key: 'container.docker.discovery[containers]' + lifetime: 7d + item_prototypes: + - + uuid: 7f3fddee7aed48c8acc26e9aa98df298 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO Read' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIORead]' + delay: '0' + history: 30d + trends: 1095d + units: B/s + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.BlockIORead + - + type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: 27f4e3e3a33c412ead03200de17bc9b5 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO Write' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIOWrite]' + delay: '0' + history: 30d + trends: 1095d + units: B/s + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.BlockIOWrite + - + type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: f59ee387b12740fc90ff6d990422e92d + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: CPU' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc]' + delay: '0' + history: 30d + trends: 1095d + value_type: FLOAT + units: '%' + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.CPUPerc + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: f56ddbaef3af4fa898ae2403a812db3c + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Dead' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Dead]' + delay: '0' + history: 7d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.inspect.State.Dead + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: e09f311feb1749cc88e8c51c8425c324 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Error' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Error]' + delay: '0' + history: 7d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.inspect.State.Error + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: b75ac0b193d2451e8ee3ce0950b7b07a + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Image' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Image]' + delay: '0' + history: 7d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.inspect.Config.Image + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: ba301501bbec40e6add5a47d2fd0ee15 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory usage' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemCurrent]' + delay: '0' + history: 30d + trends: 1095d + units: B + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.MemCurrent + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: 5895cddf57fd4b5e8917593cba941491 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory limit' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemLimit]' + delay: '0' + history: 30d + trends: 1095d + units: B + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.MemLimit + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: 640bce04f3fc483fa495ac72208effa7 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory used (%)' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc]' + delay: '0' + history: 30d + trends: 1095d + value_type: FLOAT + units: '%' + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.MemPerc + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + trigger_prototypes: + - + uuid: 9fdd469b0866409ca7889288eb5f229a + expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc])>{$DOCKER_MEM_PCT_WARN}' + recovery_mode: RECOVERY_EXPRESSION + recovery_expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc])<({$DOCKER_MEM_PCT_WARN}-2)' + name: 'Container {#DOCKER_CONTAINER_NAME} memory usage is at {ITEM.LMASTVALUE1}' + priority: AVERAGE + - + uuid: eb58fb55bc0442319650e32a8ba1faf4 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network in' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOIn]' + delay: '0' + history: 30d + trends: 1095d + units: B/s + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.NetIOIn + - + type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: 6a97e94be7d1432fb11a92072ea9e55f + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network out' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOOut]' + delay: '0' + history: 30d + trends: 1095d + units: B/s + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.NetIOOut + - + type: CHANGE_PER_SECOND + parameters: + - '' + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: 7be56a29b2464c5e96c2f4f2b3e02fba + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: OOMKilled' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},OOMKilled]' + delay: '0' + history: 7d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.inspect.State.OOMKilled + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: a5ed78ba8acf43a488b3833d14e39381 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Number of processes' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},PIDs]' + delay: '0' + history: 30d + trends: 1095d + units: '!process(es)' + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.PIDs + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: 1213e0b7fc824442b50ab4ff4cd1047b + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Restarting' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Restarting]' + delay: '0' + history: 7d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.inspect.State.Restarting + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: 418b35e93f114be986ecdd5a9d259283 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Status' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status]' + delay: '0' + history: 7d + trends: '0' + value_type: CHAR + preprocessing: + - + type: JSONPATH + parameters: + - $.inspect.State.Status + - + type: DISCARD_UNCHANGED_HEARTBEAT + parameters: + - 1h + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + trigger_prototypes: + - + uuid: 45e35825ed184b0290d1bc1ed27e48e4 + expression: 'find(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status],,"regexp","^(running|exited)$")<>1' + name: 'Container {#DOCKER_CONTAINER_NAME} status is {ITEM.LASTVALUE1}' + priority: WARNING + manual_close: 'YES' + - + uuid: ab2c34de197f4ea197e607604c936f34 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Uptime' + type: DEPENDENT + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Uptime]' + delay: '0' + history: 30d + trends: 1095d + units: s + preprocessing: + - + type: JSONPATH + parameters: + - $.stats.Uptime + master_item: + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + - + uuid: b232a5b3aedd4072a56460dd041579b1 + name: 'Docker: container {#DOCKER_CONTAINER_NAME}: Info' + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]' + history: '0' + trends: '0' + value_type: TEXT + graph_prototypes: + - + uuid: 4a9aa378970045399303dcead39c1e53 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: CPU' + graph_items: + - + sortorder: '1' + drawtype: GRADIENT_LINE + color: F63100 + item: + host: Template_App_Docker + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc]' + - + uuid: 7cd7cd8fd24d492ab7995a882b7bf9af + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO' + graph_items: + - + sortorder: '1' + drawtype: FILLED_REGION + color: FFAB91 + item: + host: Template_App_Docker + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIORead]' + - + sortorder: '2' + drawtype: FILLED_REGION + color: A5D6A7 + item: + host: Template_App_Docker + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIOWrite]' + - + uuid: 0fec757ff2f34e4fbab3be8ea455bc5f + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory' + graph_items: + - + sortorder: '1' + color: 2774A4 + item: + host: Template_App_Docker + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemCurrent]' + - + uuid: 948dccce10c54510810a64612933ca89 + name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network' + graph_items: + - + sortorder: '1' + drawtype: FILLED_REGION + color: B39DDB + item: + host: Template_App_Docker + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOIn]' + - + sortorder: '2' + drawtype: FILLED_REGION + color: 80DEEA + item: + host: Template_App_Docker + key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOOut]' + macros: + - + macro: '{$DOCKER_MEM_PCT_WARN}' + value: '80' + - + macro: '{$DOCKER_WARN_NO_LIVE_RESTORE}' + value: '1' + graphs: + - + uuid: 9c9aba9c46e145c7a8acd208edb1d147 + name: 'Docker: Number of containers' + type: STACKED + graph_items: + - + sortorder: '1' + color: 1A7C11 + item: + host: Template_App_Docker + key: 'container.docker.check[global,ContainersPaused]' + - + sortorder: '2' + color: F63100 + item: + host: Template_App_Docker + key: 'container.docker.check[global,ContainersRunning]' + - + sortorder: '3' + color: 2774A4 + item: + host: Template_App_Docker + key: 'container.docker.check[global,ContainersStopped]'