в docker, GitLab

Очистка места в private docker-registry


Ранее мы рассматривали вариант docker-установки Gitlab-сервера с расширенной функциональностью (в том числе с использованием приватного docker-registry), которая стала фундаментом для организации процесса CI (continuous integration).

Не так давно обнаружились проблемы с очисткой места, которое занимают собранные docker-образы в настроенном нами docker-registry — давайте разберемся!

Выяснилось, что в веб-интерфейсе Gitlab на вкладке Registry при нажатии на кнопку «удалить» на самом деле происходит удаление только тэга образа, а сами данные никуда не деваются и продолжают занимать место на жестком диске.

Аналогичная проблема наблюдается если docker-образ создается с одним и тем же тэгом (например, latest) — а это обычное дело для процесса CI. В этом случае, при сборке нового образа старый не удаляется (как ожидается), у него просто пропадает тэг (latest).

Например, у образа master/lebed/test:latest на самом деле на жестком диске хранится 2 версии:

ls -la /srv/gitlab/shared/registry/docker/registry/v2/repositories/master/lebed/test/_manifests/tags/latest/index/sha256
total 16
drwxr-xr-x 4 root root 4096 Jun 15 12:20 .
drwxr-xr-x 3 root root 4096 Jun 15 09:25 ..
drwxr-xr-x 2 root root 4096 Jun 15 12:20 694a3871d67d64d5c59d3f6943be3cfc0d11aae2082261735e87b1c3c58bd66b
drwxr-xr-x 2 root root 4096 Jun 15 09:25 e1f5741ced3f0280bd372baa6ca293d1033dfefc7db021cd81ca1527d2f1c08e

При частых сборках docker-образов отведенное место в docker-registry может закончиться — при этом невозможно будет пушить в него новые образы и весь процесс CI перестанет работать.

Для очистки места в приватном docker-registry необходимо выполнить следующие действия:

  • удалить старые версии тегов docker-образа;
  • удалить старые версии ревизий docker-образа;
  • запустить процесс «уборки мусора» в контейнере с docker-registry.

Рассмотрим подробнее пример выполнения данных действий.
Находясь на docker-хосте, смотрим содержимое каталога с интересующим нас docker-образом и его тэгом в каталоге /srv/gitlab/shared/registry/docker/registry/v2/repositories/{имя_докер_образа}/_manifests/tags/{тег_образа}/index/sha256
В нем должны находиться один или несколько каталогов вида e1f5741ced3f0280bd372baa6ca293d1033dfefc7db021cd81ca1527d2f1c08e. Если каталог один, то никаких действий производить не следует, если же таких директорий несколько, то нужно удалить все старые версии, оставив только одну, самую последнюю по дате создания.

Смотрим содержимое каталога с ревизиями интересующего нас docker-образа /srv/gitlab/shared/registry/docker/registry/v2/repositories/{имя_докер_образа}/_manifests/revisions/sha256
В нем должны также быть вложены директории с именами вида e1f5741ced3f0280bd372baa6ca293d1033dfefc7db021cd81ca1527d2f1c08e — точно такие же, как и в предыдущем шаге. Удаляем более старые (ориентируемся по дате создания), оставляя только один каталог.

После удаления вышеуказанных файлов запускаем процесс «уборки мусора» командой:

docker exec -it {имя_контейнера_c_registry} bin/registry garbage-collect {путь_к_конфигу_внутри_контейнера} 

В нашем случае команда выглядит так:

docker exec -it docker-registry bin/registry garbage-collect /etc/docker/registry/config.yml

Для чистки места также можно использовать скрипт clean_docker_registry.sh следующего содержания:

#!/bin/sh
REPOPATH=/srv/gitlab/shared/registry/docker/registry/v2/repositories/
echo Docker image name is $1
echo Docker image tag is $2
echo "\n";
TAGPATH=$REPOPATH$1/_manifests/tags/$2/index/sha256
REVPATH=$REPOPATH$1/_manifests/revisions/sha256

for hash in $(ls $TAGPATH -t | tail -n +2)
do
  rm -rf $TAGPATH/$hash;
  rm -rf $REVPATH/$hash;
done
docker exec -it docker-registry bin/registry garbage-collect /etc/docker/registry/config.yml

Запускаем скрипт с параметрами, первый из которых — имя docker-образа, второй — тэг docker-образа, например:

./clean_docker_registry.sh master/lebed/test latest

Не забывайте также освобождать место от неиспользуемых более docker-образов и томов, как описано здесь.

Добавить комментарий

  1. что будет если просто удалить docker-registry, например руками почистить папку registry?

    • Откровенно говоря, не пробовал, но кажется ничего хорошего не получится ))
      Так можно поступить если вы просто знакомитесь с возможностями docker и его registry, но в настоящей разработке лучше не пытаться…

      • Евгений, вопрос немного не по этой теме, но может подскажете, в какую сторону копать, я сделал следующее.
        Порядок действий:
        1. переименовал каталог с registry (например из /test в /test2)
        2. примонтировал новый диск(с б0льшим местом) в каталог в /test
        3. скопировал из test2 в test — как раньше чтобы сохранились все пути
        ——
        -в итоге registry лежит в том же каталоге, все так же, пути те же.
        -служба с докером перезапускалась
        -контейнер с registry перезапустился

        но overlayFS размер диска видит все тот же… Как будто

        Это было сделано, чтобы не чистить руками ragistry, я пытался все сделать по ывашей инструкции и даже получаю вот такие сообщения 8346 blobs marked, 22 blobs eligible for deletion…
        Но место не уменьшается, точнее я допускаю, что уменьшается, но крайне малыми порциями, но в registry ооочень много старых контейнеров.

        • У меня тоже под registry примонтирован отдельный диск:
          df -h
          Filesystem Size Used Avail Use% Mounted on
          ...
          /dev/mapper/sata-registry 99G 33G 66G 34% /srv/gitlab/shared/registry

          Делал примерно то же, что и вы:
          — остановил все контейнеры
          — остановил docker
          — примонтировал новый диск в временный каталог /mnt/tmp
          — перенес данные с сохранением прав (F6 в mc или cp -a или rsync …) на новый диск
          — примонтировал диск в /srv/gitlab/shared/registry
          — запустил докер и все контейнеры

          Все получилось, полет нормальный

        • хмм увидел вот такую вещь

          /dev/vda1 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
          /dev/vdb1 on /opt type ext4 (rw,relatime,data=ordered)
          /dev/vda1 on /var/lib/docker/overlay2 type ext4 (rw,relatime,errors=remount-ro,data=ordered)

          vdb1 — это мой новый диск,
          интересует строчка dev/vda1 on /var/lib/docker/overlay2… ,
          ее можно перемонтировать как /dev/vdb1 on /var/lib/docker/overlay2 ?

          • Это вообще никаким боком не касается docker registry

            По умолчанию docker все данные хранит в /var/lib/docker/...
            Этот каталог у вас на диске с системой (он же /, он же в вашем случае /dev/vda1)
            Если хочется перенести (хотя непонятно зачем) — останавливайте полностью весь докер, монтируйте новый диск, переносите на него данные из /var/lib/docker, потом монтируйте диск с данными в /var/lib/docker и запускайте докер