2023-09-14 15:54:48 +02:00
{ config , pkgs , . . . }:
{
# https://nixos.wiki/wiki/Docker#Installation
2024-01-12 19:43:26 +01:00
# TODO: rootless Docker equivalent with root privileges? https://nixos.wiki/wiki/Docker#Rootless_docker
2023-09-14 15:54:48 +02:00
# TODO: run as systemd services. https://nixos.wiki/wiki/Docker#docker_containers_as_systemd_services
virtualisation = {
docker = {
enable = true ;
# As we use btrfs, we enable the according storageDriver option.
storageDriver = " b t r f s " ;
2023-10-10 17:21:41 +02:00
# IPv6 support.
# https://search.nixos.org/options?channel=23.05&show=virtualisation.docker.daemon.settings
# https://docs.docker.com/config/daemon/ipv6/#use-ipv6-for-the-default-bridge-network
# TODO: See notes in Jinja-Compose/proxy.yml.jinja2 why this is not yet ready to use.
# daemon.settings = {
# # Enable IPv6 networking on the default network.
# ipv6 = true;
# # Assign a subnet to the default bridge network, enabling dynamic IPv6 address allocation.
# fixed-cidr-v6 = "2001:db8:1::/64";
# # Enable additional IPv6 packet filter rules, providing network isolation and port mapping.
# # This parameter requires experimental to be set to `true`.
# ip6tables = true;
# experimental = true;
# };
2023-10-09 12:06:15 +02:00
# Run `docker system prune -f ${autoPrune.flags}` every week.
2023-10-16 15:13:12 +02:00
# This creates `docker-prune.service` and `docker-prune.timer`.
2023-09-14 15:54:48 +02:00
autoPrune . enable = true ;
autoPrune . dates = " w e e k l y " ;
# https://docs.docker.com/engine/reference/commandline/system_prune/#options
autoPrune . flags = [
" - - a l l "
# https://docs.docker.com/engine/reference/commandline/system_prune/#filter
# https://pkg.go.dev/maze.io/x/duration#ParseDuration
2023-10-09 12:06:15 +02:00
# `7d` could not be parsed, thus we use `168h`
" - - f i l t e r u n t i l = 1 6 8 h "
# `--volumes` can't be used together with `--filter`.
# Thus we added our own service below.
#--volumes
2023-09-14 15:54:48 +02:00
] ;
} ;
} ;
2023-10-08 20:03:00 +02:00
2023-10-09 12:06:15 +02:00
# Prune docker volumes.
# This is a slightly modified copy of https://github.com/NixOS/nixpkgs/blob/5a237aecb57296f67276ac9ab296a41c23981f56/nixos/modules/virtualisation/docker.nix#L211C5-L226
systemd . services . " d o c k e r - p r u n e - v o l u m e s " = {
description = " P r u n e d o c k e r v o l u m e s " ;
restartIfChanged = false ;
unitConfig . X-StopOnRemoval = false ;
serviceConfig . Type = " o n e s h o t " ;
script = ''
$ { pkgs . docker } /bin/docker system prune - f - - all - - volumes
'' ;
2023-10-16 15:13:12 +02:00
# Run weekly after `docker-prune.service` has finished.
# Reason: Only one `docker system prune` command can be run at a time.
2023-10-09 12:06:15 +02:00
startAt = " w e e k l y " ;
2023-10-16 15:13:12 +02:00
# Start the specified units when this unit is started,
# and stop this unit when the specified units are stopped or fail.
2023-10-09 12:06:15 +02:00
requires = [ " d o c k e r . s e r v i c e " ] ;
2023-10-16 15:13:12 +02:00
# If the specified units are started at the same time as this unit,
# delay this unit until they have started.
after = [ " d o c k e r . s e r v i c e " " d o c k e r - p r u n e . s e r v i c e " ] ;
2023-10-09 12:06:15 +02:00
} ;
2023-10-08 20:03:00 +02:00
# Monitor unhealthy Docker containers.
systemd . timers . " d o c k e r - h e a l t h " = {
wantedBy = [ " t i m e r s . t a r g e t " ] ;
partOf = [ " d o c k e r - h e a l t h . s e r v i c e " ] ;
timerConfig = {
OnBootSec = " 0 m " ;
OnUnitInactiveSec = " 3 m " ;
AccuracySec = " 1 5 s " ;
RandomizedDelaySec = " 1 5 s " ;
} ;
} ;
systemd . services . " d o c k e r - h e a l t h " = {
serviceConfig = {
Type = " o n e s h o t " ;
PrivateTmp = true ;
# `docker` requires root access.
User = " r o o t " ;
Nice = 19 ;
IOSchedulingClass = " i d l e " ;
} ;
path = with pkgs ; [
docker
] ;
# If there are no unhealthy Docker containers, the output of `docker ps -f health=unhealthy` is just one line:
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# We filter this line with `grep -v`.
# As a result, grep returns exit code 1 if there are no unhealthy containers (as not a single line is printed).
# Thus, we prefix the whole command with `!`.
# Lastly, we redirect stdout to stderr with `1>&2` so that unhealthy containers are written to stderr.
script = ''
set - eu - o pipefail
2024-01-12 19:43:26 +01:00
! docker ps - f health = unhealthy | grep - v ' CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES' 1 > & 2
2023-10-08 20:03:00 +02:00
'' ;
} ;
2023-09-14 15:54:48 +02:00
}