Automatické čištění Docker cache volumes pro Gitlab Runner
Jak vyřešit problém s neustále rostoucími Docker volumes pro GitLab Runner cache a nastavit jejich automatické čištění.
V tomto článku
Problém
GitLab Runner při použití Docker executoru vytváří volumes pro ukládání cache mezi buildy. Tyto volumes však nemají žádný vestavěný mechanismus pro automatické čištění a postupem času mohou narůst do obřích rozměrů – není výjimkou vidět stovky gigabajtů či dokonce terabajty obsazeného místa.
Volumes můžete zobrazit příkazem:
docker volume ls | grep runner
A jejich velikost zjistíte pomocí:
for vol in $(docker volume ls -q | grep -E '^runner-.*-cache'); do
SIZE=$(docker run --rm -v "$vol":/data alpine du -sh /data 2>/dev/null | cut -f1)
echo "$SIZE $vol"
done
Typický výstup může vypadat následovně:
132G runner-yd6eca4h-project-100-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
124G runner-88bmy4dg2-project-100-concurrent-0-cache-3c3f060a0374fc8bc39395164f415a70
29G runner-0558e6a41bfb19b22a086fc2330d186c-cache-3c3f060a0374fc8bc39395164f415a70
Všimněte si dvou různých formátů pojmenování – starší verze GitLab Runneru (před 15.x) používaly 32-znakový hash, novější verze používají formát runner-{system_id}-project-{id}-concurrent-{n}.
Příčina
GitLab Runner vytváří nové cache volumes při:
- změně
cache:keyv.gitlab-ci.yml - přeregistraci runneru (nové
system_id) - změně projektu nebo větve (záleží na konfiguraci cache key)
Staré volumes však zůstávají na disku a nejsou automaticky mazány. Navíc při přeregistraci runneru vznikne nové system_id a všechny předchozí volumes se stanou "osiřelými".
Aktuální system_id vašeho runneru zjistíte příkazem:
cat /etc/gitlab-runner/.runner_system_id
Řešení
Jednorázové vyčištění
GitLab Runner obsahuje oficiální skript pro vyčištění cache. Na Debian/Ubuntu je součástí balíčku gitlab-runner a najdete jej v /usr/share/gitlab-runner/clear-docker-cache.
/usr/share/gitlab-runner/clear-docker-cache
Skript nabízí několik možností:
# Zobrazí nápovědu
/usr/share/gitlab-runner/clear-docker-cache help
# Smaže pouze osiřelé volumes (výchozí)
/usr/share/gitlab-runner/clear-docker-cache prune-volumes
# Smaže všechny runner cache volumes
/usr/share/gitlab-runner/clear-docker-cache space
Oficiální skript obsahuje workaround pro změnu chování v Docker 23.0, který uměle snižuje API verzi na 1.41. U novějších verzí Dockeru (API 1.44+) to způsobuje chybu, např.:
Error response from daemon: client version 1.41 is too old. Minimum supported API version is 1.44
V takovém případě použijte přímo Docker příkazy:
# Smaže volumes s GitLab Runner labelem
docker volume prune -f --filter "label=com.gitlab.gitlab-runner.managed=true"
Pro ruční smazání všech cache volumes:
docker volume ls -q | grep -E '^runner-.*-cache' | xargs -r docker volume rm
Automatické čištění pomocí cron
Pro pravidelné čištění vytvořte soubor /etc/cron.d/gitlab-runner-cache-cleanup:
# Každou neděli ve 3:00 smaže nepoužívané runner cache volumes
0 3 * * 0 root docker volume prune -f --filter "label=com.gitlab.gitlab-runner.managed=true" >> /var/log/gitlab-runner-cache-cleanup.log 2>&1
Prevence
Pro omezení růstu cache přímo v projektech lze v .gitlab-ci.yml nastavit expiraci:
cache:
key:
files:
- package-lock.json # nová cache pouze při změně dependencies
paths:
- node_modules/
expire_in: 1 week
Nastavení expire_in však funguje pouze na úrovni GitLab serveru, ne na úrovni Docker volumes. Pro skutečné omezení velikosti na úrovni runneru je nutné použít výše popsané čištění.