Рассмотрим способы удаления различных артефактов Docker и элементов кэша сборки, которые занимают место на диске, по отдельности или полностью локально и в CI. Docker сохраняет кэш сборки, контейнеры, образы и тома на диске.
Со временем эти элементы могут занимать много места в вашей системе, как локально, так и в CI.

Кэширование слоев
Docker использует кэширование слоёв для повторного использования ранее вычисленных результатов сборки. Каждая инструкция в Dockerfile связана со слоем, который содержит изменения, вызванные выполнением этой инструкции.
Если предыдущие слои, а также входные данные для инструкции не изменились, а инструкция уже была выполнена и кэширована ранее, Docker будет использовать для неё кэшированный слой. В противном случае Docker перестроит этот слой и все последующие слои.

Использование кэшированного слоя выполняется намного быстрее, чем повторный расчёт инструкции с нуля. Поэтому, как правило, вы хотите, чтобы как можно большая часть сборки Docker выполнялась из кэша, а перестраивались только те слои, которые изменились с момента последней сборки.
Одним из основных факторов, влияющих на то, сколько слоёв в вашем образе необходимо пересобрать, является порядок операций в Dockerfile.
Сколько пространства Docker использует на диске?
docker system df
docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 138 34 36.18GB 34.15GB (94%)
Containers 74 18 834.8kB 834.6kB (99%)
Local Volumes 118 6 15.31GB 15.14GB (98%)
Build Cache 245 0 1.13GB 1.13GB
К счастью, Docker позволяет освободить место на диске от неиспользуемых образов, контейнеров и томов.
Периодическая обрезка
Чтобы безопасно удалить остановленные контейнеры, неиспользуемые сети и висячие образы, рекомендуется время от времени выполнять следующую команду:
docker system prune
Несколько более рискованный вариант — это:
docker system prune -a
Это также удаляет все образы, не связанные с работающим контейнером. Это может показаться немного радикальным решением, но Docker повторно загрузит все необходимые образы. Первая попытка будет немного медленнее, но затем образ будет кэширован для дальнейшего использования.
В следующих разделах описаны дополнительные способы удаления определенных элементов.
Удаление Dockerimage
Docker образ — это снимок с диска приложения, такого как веб-сервер, языковая среда выполнения или система управления базами данных. Вы можете просмотреть все изображения, как активные, так и висячие (те, которые не связаны с контейнером), введя:
docker image ls -a
Изображение Docker можно удалить, введя:
docker image rm <name_or_id>
В эту команду можно добавить любое количество изображений — разделяйте их пробелами.
Удаление неиспользуемых Docker образов
Для удаления неиспользуемых образов из системы мы можем использовать команду docker image prune
.
По умолчанию он удаляет только висячие изображения, которые не связаны ни с одним контейнером и не имеют тегов.
docker image prune -fDeleted Images:deleted: sha256:6f096c9fa1568f7566d4acaf57d20383851bcc433853df793f404375c8d975d6... Total reclaimed space: 2.751GB
Мы освободили более 2,7 ГБ памяти, удалив лишние изображения. Но, если мы вспомним вывод нашей docker system df
команды, у нас есть 34,15 ГБ удаляемых изображений.
Откуда берется остальная часть этого пространства? Это изображения в нашей системе, которые помечены или связаны с контейнером. Мы можем запустить команду docker image prune- a
, чтобы принудительно удалить эти изображения, если они не используются.
docker image prune -a -fDeleted Images:untagged: k8s.gcr.io/etcd:3.4.13-0untagged: k8s.gcr.io/etcd@sha256:4ad90a11b55313b182afc186b9876c8e891531b8db4c9bf1541953021618d0e2deleted: sha256:0369cf4303ffdb467dc219990960a9baa8512a54b0ad9283eaf55bd6c0adb934deleted: sha256:f3cecccfe2bea1cbd18db5eae847c3a9c8253663bf30a41288f541dc1470b41e Total reclaimed space: 22.66GB
Таким образом мы удаляем все неиспользуемые изображения, не связанные с контейнером, а не только висящие в воздухе.
Удаление Docker контейнера
Docker контейнер — это запущенный экземпляр образа, и любое количество контейнеров может быть запущено из одного и того же. Контейнеры обычно небольшие, потому что они не имеют состояния и ссылаются на файловую систему образа. Просмотрите все контейнеры, как запущенные, так и остановленные, введя:
docker container ls -a
Вы можете удалить контейнер только после его остановки. Остановите контейнеры, введя:
docker container stop <name_or_id>
Затем контейнеры можно удалить, введя:
docker container rm <name_or_id>
Опять же, в эту команду можно добавить любое количество имён/идентификаторов контейнеров, разделённых пробелами.
Обычно нет необходимости сохранять остановленные контейнеры. Опцию — rm
можно добавить к любой docker run
команде, чтобы автоматически удалять контейнер после его завершения.
Мы можем использовать команду docker container prune
для очистки дискового пространства, используемого контейнерами. Эта команда удалит из системы все остановленные контейнеры.
Здесь и в последующих примерах мы можем опустить флаг -f
для получения запроса на подтверждение перед удалением артефактов.
docker container prune -fDeleted Containers:399d7e3679bf9b14a1c7045cc89c056f2efe31d0a32f186c5e9cb6ebbbf42c8e Total reclaimed space: 834.6kB
Какие контейнеры не используются?
Мы можем увидеть идентификаторы неиспользуемых контейнеров, выполнив команду docker ps
с фильтрами по статусу контейнера. Контейнер считается неиспользуемым, если его статус равен exited
или dead
.
docker ps --filter status=exited --filter status=dead -q11bc2aa92622355901f38ecb263e9bde1f24
Удаление всех контейнеров
Если мы хотим удалить все контейнеры из системы, мы можем остановить все запущенные контейнеры, а затем использовать ту же команду prune. Для этого введите вывод команды docker ps -q
в docker stop
или docker kill
команду, если вы хотите принудительно завершить работу контейнера.
docker stop $(docker ps -q)docker container prune
Другой вариант — это docker rm
команда, которую можно использовать с docker ps -a -q
для удаления всех контейнеров.
docker rm $(docker ps -a -q)
Примечание: Команда docker rm
принудительно удаляет запущенный контейнер с помощью SIGKILL
сигнала. Это то же самое, что и команда docker kill
. Команда docker ps -a -q
выводит список всех контейнеров в системе, включая запущенные, и передает его в команду docker rm
.
Приведение в порядок сети
Контейнеры могут быть подключены к управляемой Docker сети, чтобы они могли взаимодействовать друг с другом. Это файлы конфигурации, которые не занимают много места на диске. Чтобы просмотреть все сети Docker, введите:
docker network ls
Одну или несколько неиспользуемых сетей можно удалить, введя:
docker network rm <name_or_id>
Опять же, в эту команду можно добавить любое количество сетевых имён/идентификаторов, разделённых пробелами.
Удаление томов
Docker Том — это образ виртуального диска. Его необходимо прикрепить к работающему контейнеру, чтобы он мог сохранять файлы или другую информацию о состоянии между перезапусками. Размеры тома зависят от приложения, использующего его, но типичной базе данных потребуется несколько сотен мегабайт пространства, даже если она в основном пуста.
Просмотрите все дисковые тома, управляемые Docker, введя:
docker volume ls
При удалении тома Docker все его данные будут безвозвратно удалены! Вернуться назад будет невозможно.
Если вы разрабатываете приложение на основе базы данных, обычно целесообразно сохранять один или несколько дампов данных, которые можно использовать для воссоздания определенного набора записей. Большинство клиентских инструментов для работы с базами данных предоставляют возможность дампа или экспорта, например, с помощью ссылки Экспорт в Adminer.
Большинство систем баз данных предоставляют инструмент для резервного копирования, такой как mysqldump
утилита в MySQL. Их можно запустить в работающем контейнере с помощью docker exec
команды.
Следующая команда Linux/macOS создает резервную копию базы данных MySQL с именем mydb
, работающей в контейнере с именем mysql
, в файл с именем backup.sql
. Используется пользователь MySQL root
с паролем mysecret
:
docker exec mysql /usr/bin/mysqldump -u root -pmysecret mydb > backup.sql
эквивалентная команда для Windows PowerShell:
docker exec mysql /usr/bin/mysqldump -u root -pmysecret -r mydb | Set-Content backup.sql
Вы также можете копировать файлы данных в работающий контейнер или из него с помощью docker cp
команды. При этом передаются пути к источнику и месту назначения, где контейнеры указываются по имени/идентификатору, за которым следует двоеточие и путь, например:
docker cp mycontainer:/some/file ./host/directory
Предполагая, что ваши данные в безопасности, вы можете удалить любой неиспользуемый том, введя:
docker volume rm <name>
Все неиспользуемые тома Docker — те, которые в данный момент не подключены к работающему контейнеру — можно удалить с помощью:
docker volume prune
В качестве альтернативы docker volume prune -a
я удалю их все. Вы ведь сначала сделали резервную копию, не так ли?..
В Docker тома никогда не очищаются автоматически, потому что они могут содержать ценные данные. Но если мы знаем, что нам больше не нужны данные в томе, мы можем удалить его с помощью docker volume prune
команды. Это удаляет все анонимные тома, которые не используются ни в одном контейнере.
docker volume prune -fTotal reclaimed space: 0B
Интересно, что мы видим, что не освободили ни одного места. Это происходит потому, что у нас есть тома, связанные с контейнерами. Мы можем увидеть эти тома, запустив docker volume ls
DRIVER VOLUME NAMElocal 0a44f085adc881ac9bb9cdcd659c28910b11fdf4c07aa4c38d0cca21c76d4ac4local 0d3ee99b36edfada7834044f2caa063ac8eaf82b0dda8935ae9d8be2bffe404c...
Мы получаем вывод, в котором отображается драйвер и имя тома. Команда docker volume prune
удаляет только анонимные тома. Эти тома не имеют имени и не имеют конкретного источника за пределами контейнера. Мы можем использовать docker volume rm -a
команду для удаления всех томов.
docker volume prune -a -fDeleted Volumes:c0c240b680d70fffef420b8699eeee3f0a49eec4cc55706036f38135ae121be02ce324adb91e2e6286d655b7cdaaaba4b6b363770d01ec88672e26c3e2704d9e Total reclaimed space: 15.31GB
Полный чистый старт
Все неиспользуемые контейнеры, образы, тома и сети можно удалить с помощью одной команды:
docker system prune -a --volumes
Добавьте -f
если вы хотите принудительно выполнить очистку без запроса подтверждения. Ваша система вернется в исходное состояние без каких-либо данных Docker.
Очистка файлов Docker по CRON
Самый простой способ подчищать за Docker это — ежедневно запускать cron-задание для выполнения нашей команды обрезки.
docker system prune -af --filter "until=$((30*24))h"
команда, заставляющая docker удалить все неиспользуемые контейнеры
Давайте немного разберёмся, чтобы понять, что здесь происходит:
- Удаление неиспользуемых контейнеров в системе Docker — мы просим Docker удалить неиспользуемые контейнеры.
- -af — здесь мы объединили два флага. Добавление флага -a заставляет Docker искать не только зависшие контейнеры, но и все контейнеры, которые больше не используются. Флаг -f просто предотвращает появление запроса на подтверждение, который обычно появляется, когда пользователь подтверждает удаление.
Только одно предупреждение: «неиспользуемые» означает «изображения, на которые не ссылается ни один контейнер»: будьте осторожны при использовании -a!
- —filter — добавление фильтра позволяет указать возраст изображений, которые мы хотим удалить. В данном случае это любые изображения старше 30 дней или 1 месяца. Здесь мы используем базовую математику в bash, так как bash поддерживает только h (часы). Поэтому давайте вычислим 30 * 24 часа, что даст нам 1 месяц в часах, что обычно ограничивает количество контейнеров несколькими гигабайтами. Вы можете сократить это время, если у вас очень мало места на диске вашего VPS.
давайте создадим новый файл в Cron-файле для размещения нашей команды:
cd /etc/cron.daily
sudo nano docker-prune
Команда для создания нового файла в папке /etc/cron.daily/
Как только файл откроется, добавьте созданную нами команду prune и сообщите ОС, что это файл bash
#!/bin/bash
docker system prune -af --filter "until=$((30*24))h"
содержимое файла docker-prune, который мы только что создали
После добавления команды нажмите Ctrl + O, а затем Ctrl + X, чтобы сохранить и закрыть файл
Теперь, когда мы создали файл, нам нужно сообщить операционной системе, что он должен быть исполняемым, с помощью следующей команды:
sudo chmod +x /etc/cron.daily/docker-prune
команда, чтобы сделать файл, который мы только что создали, исполняемым
И это всё. Теперь Docker будет выполнять эту команду ежедневно.
Ссылки:
How to clear Docker cache and free up space on your system
How to Prune Docker Images Automatically with a Daily Cron job