Как удалить старые и неиспользуемые изображения Docker


763

При долгом запуске Docker в системе много образов. Как я могу безопасно удалить все неиспользуемые образы Docker, чтобы освободить хранилище?

Кроме того, я также хочу удалить изображения, сделанные месяцами назад, которые имеют правильные TAG.

Поэтому я не прошу удалять только непомеченные изображения. Я ищу способ удаления общих неиспользуемых изображений, который включает в себя как нетегированные, так и другие изображения, такие как извлеченные несколько месяцев назад с правильным TAG.

Ответы:


1403

Обновление, сентябрь 2016 г .: Docker 1.13: PR 26108 и commit 86de7c0 вводят несколько новых команд, чтобы упростить визуализацию того, сколько места занимают данные демона docker на диске и что позволяет легко очистить «ненужный» избыток.

docker system pruneудалит ВСЕ висячие данные (т.е. по порядку: контейнеры остановлены, тома без контейнеров и изображения без контейнеров). Даже неиспользованные данные, с -aвозможностью.

У вас также есть:

Для неиспользуемых изображений используйте docker image prune -a(для удаления висячих и незапущенных изображений).
Предупреждение: « не используется » означает «изображения, на которые не ссылается ни один контейнер»: будьте осторожны перед использованием -a.

Как показано в AL «s ответ , docker system prune --allбудут удалены все неиспользуемые изображения не только оборванных те ... , которые могут быть немного слишком много.

Объединение docker xxx pruneс --filterопцией может быть отличным способом ограничения сокращения ( Docker SDK API минимум 1.28, поэтому docker 17.04+ )

В настоящее время поддерживаются следующие фильтры:

  • until (<timestamp>) - удалять только контейнеры, изображения и сети, созданные до заданной отметки времени
  • label( label=<key>, label=<key>=<value>, label!=<key>, Или label!=<key>=<value>) - только удалить контейнеры, изображения, сети и объемы с (или без , в случае , если label!=...используется) указанные метки.

См. « Обрезать изображения » для примера.


Оригинальный ответ (сентябрь 2016 г.)

Я обычно делаю:

docker rmi $(docker images --filter "dangling=true" -q --no-trunc)

У меня есть псевдоним для удаления этих [болтающихся изображений] 13 :drmi

dangling=trueФильтр находит неиспользуемые изображения

Таким образом, любое промежуточное изображение, на которое больше не ссылается помеченное изображение, удаляется.

Я делаю то же самое в первую очередь для вышедших процессов (контейнеров)

alias drmae='docker rm $(docker ps -qa --no-trunc --filter "status=exited")'

Как haridsv баллов из в комментариях :

Технически, вы должны сначала очистить контейнеры перед очисткой изображений, так как это поймает больше висящих изображений и меньше ошибок .


Джесс Фразелль (jfrazelle) имеет функцию bashrc :

dcleanup(){
    docker rm -v $(docker ps --filter status=exited -q 2>/dev/null) 2>/dev/null
    docker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2>/dev/null
}

Чтобы удалить старые изображения, а не только изображения без привязок, вы можете рассмотреть следующие вопросы docker-gc:


Простой Docker-контейнер и скрипт для сборки мусора изображений.

  • Контейнеры, вышедшие более часа назад, удаляются.
  • Изображения, которые не принадлежат ни одному из оставшихся контейнеров после этого, удаляются.

29
Есть ли документация о том, что на "dangling=true"самом деле означает?
CivFan

1
Этот сценарий не может удалить некоторые изображения, извлеченные несколько месяцев назад
Quanlong

2
dcleanupявляется удивительным!
Quanlong

4
@herm Во-первых, docker system pruneудаляет гораздо больше, чем просто изображения. Обязательно используйте docker image pruneвместо этого. И будьте очень осторожны с -a: а docker system prune -aможет иметь разрушительный эффект (также удаляя объемы). Наконец, да, -aудаляет неиспользуемые изображения, я буду редактировать ответ.
VonC

2
@stom: «неиспользованный» означает «изображения, на которые не ссылается ни один контейнер, но висящий означает не помеченный вообще (просто идентификатор).
VonC

125

Обновление второе (2017-07-08):

Обратитесь (снова) к VonC, используя еще более позднюю версию system prune. Нетерпеливый может пропустить приглашение с -f, --forceопцией:

docker system prune -f

Нетерпеливые и безрассудные могут дополнительно удалить «неиспользуемые изображения, а не только свисающие» с помощью -a, --allопции:

docker system prune -af

https://docs.docker.com/engine/reference/commandline/system_prune/

Обновить:

Обратитесь к ответу VonC, который использует недавно добавленные pruneкоманды. Вот соответствующее удобство псевдонима оболочки:

alias docker-clean=' \
  docker container prune -f ; \
  docker image prune -f ; \
  docker network prune -f ; \
  docker volume prune -f '

Старый ответ:

Удалить остановленные (вышедшие) контейнеры:

$ docker ps --no-trunc -aqf "status=exited" | xargs docker rm

Удалить неиспользуемые (висячие) изображения:

$ docker images --no-trunc -aqf "dangling=true" | xargs docker rmi

Если вы проявили крайнюю осторожность в отношении безвозвратной потери данных , вы можете удалить неиспользуемые (висячие) тома (версии 1.9 и выше):

$ docker volume ls -qf "dangling=true" | xargs docker volume rm

Вот они в удобном псевдониме оболочки:

alias docker-clean=' \
  docker ps --no-trunc -aqf "status=exited" | xargs docker rm ; \
  docker images --no-trunc -aqf "dangling=true" | xargs docker rmi ; \
  docker volume ls -qf "dangling=true" | xargs docker volume rm'

Ссылки:


3
Я бы проявил осторожность с очисткой тома. И автоматически созданные тома контейнера, и именованные тома, которые в данный момент не используются, перечислены вместе с dangling = true.
BMitch

1
@BMitch, ты абсолютно прав; Я добавил строгое предупреждение к docker volume rmрецепту. Я буду рад любым предложениям, которые у вас есть.
рубит

1
Я бы хотел, чтобы докер дал нам другую опцию фильтра для названных томов. Если я придумаю хороший обходной путь, я обязательно поделюсь.
BMitch

2
да, но, к сожалению, он не отделяет именованный том от тома анонимного контейнера простым флагом. Команда, которую я использовал, docker volume ls -qf dangling=true | egrep '^[a-z0-9]{64}$' | xargs --no-run-if-empty docker volume rmбудет работать до тех пор, пока вы никогда не назовете свои тома чем-то похожим на guid. Я могу настроить это для нового синтаксиса фильтра.
BMitch

1
Удаление неиспользуемых (висячих) томов действительно помогает нам!
Кейн

61

Чтобы удалить старые помеченные изображения, возраст которых превышает месяц:

$ docker images --no-trunc --format '{{.ID}} {{.CreatedSince}}' \
    | grep ' months' | awk '{ print $1 }' \
    | xargs --no-run-if-empty docker rmi

Обратите внимание, что не удастся удалить изображения, которые используются контейнером, на который есть ссылка в репозитории, имеют зависимые дочерние изображения ... что, вероятно, то, что вам нужно. Остальное просто добавь -fфлаг.

Пример /etc/cron.daily/docker-gcскрипта:

#!/bin/sh -e

# Delete all stopped containers (including data-only containers).
docker ps -a -q --no-trunc --filter "status=exited" | xargs --no-run-if-empty docker rm -v

# Delete all tagged images more than a month old
# (will fail to remove images still used).
docker images --no-trunc --format '{{.ID}} {{.CreatedSince}}' | grep ' months' | awk '{ print $1 }' | xargs --no-run-if-empty docker rmi || true

# Delete all 'untagged/dangling' (<none>) images
# Those are used for Docker caching mechanism.
docker images -q --no-trunc --filter dangling=true | xargs --no-run-if-empty docker rmi

# Delete all dangling volumes.
docker volume ls -qf dangling=true | xargs --no-run-if-empty docker volume rm

2
+1 За команду удалить старые образы докеров. Это немного странно, но решение оригинально и отлично работает :)
Рик,

3
Это хорошо, однако я думаю, что это только удаляет образы докеров, которые по крайней мере 4 месяца . .CreatedSinceиспользует недели в качестве единицы времени при выводе даже на изображения, которым много недель, например 12 weeks.
joelittlejohn

2
Это сработало для меня, красиво и просто:docker images | grep ' months' | awk '{ print $3 }' | xargs --no-run-if-empty docker rmi -f
Кент Булл

34

Другие ответы великолепны, а именно:

docker system prune # doesn't clean out old images
docker system prune --all # cleans out too much

Но мне нужно было что-то посередине двух команд, так что filterопция была то, что мне нужно:

docker image prune --all --filter "until=4320h" # delete images older than 6 months ago; 4320h = 24 hour/day * 30 days/month * 6 months

Надеюсь, это поможет :)

Для справки: https://docs.docker.com/config/pruning/#prune-images


1
Очень недооцененный ответ! Возможность обрезать дату отсечки чрезвычайно полезна.
Ник Рейман

24

Предполагая, что у вас Docker 1.13 или выше, вы можете просто использовать команды удаления. Для вашего вопроса специально для удаления старых изображений, вы хотите первое.

# Remove unused images
docker image prune

# Remove stopped containers.
docker container prune

# Remove unused volumes
docker volume prune

# Remove unused networks
docker network prune

# Command to run all prunes:
docker system prune

Я бы порекомендовал не привыкать к использованию docker system pruneкоманды. Я считаю, что пользователи будут случайно удалять вещи, которые они не имеют в виду. Лично я буду в основном быть с помощью docker image pruneи docker container pruneкоманды.


4
Вы не хотите обрезать неиспользуемые сети? например, если все контейнеры остановлены, и я удаляю эти сети, как они будут работать, если я их запущу. Создаются ли сети вместе с Docker Run?
эффект

@ Влияние Я полностью согласен, и, боже, заметьте, что я оставил отключение сети. Я включил это и добавил часть в конце, заявляя, что я не рекомендовал бы использовать docker system pruneкроме отдельных черносливов.
Programster

15

До сих пор (Docker версия 1.12) мы использовали следующую команду для удаления всех запущенных контейнеров. Также, если мы хотим удалить тома, мы можем сделать это вручную, используя соответствующий тег -v в следующей команде.

Удалить все вышедшие контейнеры

docker rm $(docker ps -q -f status=exited)

Удалить все остановленные контейнеры

docker rm $(docker ps -a -q)

Удалить все запущенные и остановленные контейнеры

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

Удалить все контейнеры без каких-либо критериев

docker container rm $(docker container ps -aq)

Но в версии 1.13 и выше для полной очистки системы мы можем напрямую использовать следующую команду:

docker system prune

Все неиспользуемые контейнеры, изображения, сети и тома будут удалены. Мы также можем сделать это с помощью следующих команд, которые очищают отдельные компоненты:

docker container prune
docker image prune
docker network prune
docker volume prune


13

Следующая команда удалит изображения старше 48 часов.

$ docker image prune --all --filter until=48h

1
С помощью фильтров также можно составить список всех версий до указанной версии, docker image ls --all --filter reference=monolito --filter before=monolito:0.1.8а затем применить команду rmi для удаления. docker rmi $(docker image ls -q --all --filter reference=monolito --filter before=monolito:0.1.8)
Родвлопес

9

Я недавно написал скрипт для решения этой проблемы на одном из моих серверов:

#!/bin/bash

# Remove all the dangling images
DANGLING_IMAGES=$(docker images -qf "dangling=true")
if [[ -n $DANGLING_IMAGES ]]; then
    docker rmi "$DANGLING_IMAGES"
fi

# Get all the images currently in use
USED_IMAGES=($( \
    docker ps -a --format '{{.Image}}' | \
    sort -u | \
    uniq | \
    awk -F ':' '$2{print $1":"$2}!$2{print $1":latest"}' \
))

# Get all the images currently available
ALL_IMAGES=($( \
    docker images --format '{{.Repository}}:{{.Tag}}' | \
    sort -u \
))

# Remove the unused images
for i in "${ALL_IMAGES[@]}"; do
    UNUSED=true
    for j in "${USED_IMAGES[@]}"; do
        if [[ "$i" == "$j" ]]; then
            UNUSED=false
        fi
    done
    if [[ "$UNUSED" == true ]]; then
        docker rmi "$i"
    fi
done

8

Вот скрипт для очистки образов Docker и освобождения места.

#!/bin/bash -x
## Removing stopped container
docker ps -a | grep Exited | awk '{print $1}' | xargs docker rm

## If you do not want to remove all container you can have filter for days and weeks old like below
#docker ps -a | grep Exited | grep "days ago" | awk '{print $1}' | xargs docker rm
#docker ps -a | grep Exited | grep "weeks ago" | awk '{print $1}' | xargs docker rm

## Removing Dangling images
## There are the layers images which are being created during building a Docker image. This is a great way to recover the spaces used by old and unused layers.

docker rmi $(docker images -f "dangling=true" -q)

## Removing images of perticular pattern For example
## Here I am removing images which has a SNAPSHOT with it.

docker rmi $(docker images | grep SNAPSHOT | awk '{print $3}')

## Removing weeks old images

docker images | grep "weeks ago" | awk '{print $3}' | xargs docker rmi

## Similarly you can remove days, months old images too.

Оригинальный сценарий

https://github.com/vishalvsh1/docker-image-cleanup

Обычно Docker хранит все временные файлы, связанные со сборкой изображений и слоями, в

/ Var / Библиотека / Докер

Этот путь является локальным для системы, обычно в корневом разделе «/» .

Вы можете смонтировать место на диске побольше, переместить содержимое /var/lib/dockerв новое место монтирования и сделать символическую ссылку.

Таким образом, даже если образы Docker занимают место, это не повлияет на вашу систему, так как будет использоваться другое место монтирования.

Исходное сообщение: Управление образами Docker на локальном диске.


6

Я использую эту команду:

export BEFORE_DATETIME=$(date --date='10 weeks ago' +"%Y-%m-%dT%H:%M:%S.%NZ")
docker images -q | while read IMAGE_ID; do
    export IMAGE_CTIME=$(docker inspect --format='{{.Created}}' --type=image ${IMAGE_ID})
    if [[ "${BEFORE_DATETIME}" > "${IMAGE_CTIME}" ]]; then
        echo "Removing ${IMAGE_ID}, ${BEFORE_DATETIME} is earlier then ${IMAGE_CTIME}"
        docker rmi -f ${IMAGE_ID};
    fi;
done

Это удалит все изображения, время создания которых превышает 10 недель назад.


Я думаю, что вы поменялись IMAGE_CTIMEи BEFORE_DATETIMEв этой echoкоманде
Udo G

5

Если вы хотите удалить изображения, извлеченные X месяцев назад, вы можете попробовать следующий пример, который удаляет изображения, созданные три месяца назад:

three_months_old_images=`docker images | grep -vi "<none>" | tr -s ' ' | cut -d" " -f3,4,5,6 | grep "3 months ago" | cut -d" " -f1`
docker rmi $three_months_old_images

1
Это не правильно. При этом удаляются изображения, созданные 3 месяца назад, а не изображения, извлеченные 3 месяца назад (если вы извлекаете их из удаленного источника, им уже может быть 3 месяца).
Эндрю Ферье

Это помогло мне создать больше фильтров, основанных на разных критериях
david.sansay


3

docker system prune -a

(Вам будет предложено подтвердить команду. Используйте -fдля принудительного запуска, если вы знаете, что делаете.)


5
Это опасно , см. Другие комментарии об docker system pruneудалении даже именованных томов с помощью -a.
RichVel

3

@VonC уже дал очень хороший ответ, но для полноты здесь приведен небольшой скрипт, который я использовал --- и который также уничтожает любые поручающие процессы Docker, если они у вас есть:

#!/bin/bash

imgs=$(docker images | awk '/<none>/ { print $3 }')
if [ "${imgs}" != "" ]; then
   echo docker rmi ${imgs}
   docker rmi ${imgs}
else
   echo "No images to remove"
fi

procs=$(docker ps -a -q --no-trunc)
if [ "${procs}" != "" ]; then
   echo docker rm ${procs}
   docker rm ${procs}
else
   echo "No processes to purge"
fi

Прекрасно работает, но все еще можно получить Error response from daemon: You cannot remove a running container. Добавлено docker kill $(docker ps -q)перед строкой 3 по адресу
Винсент

Почему бы не использовать $(docker images -q)вместо $(docker images | awk '/<none>/ { print $3 }')?
19

1
@SeF: если я docker images -qполучу вектор идентификаторов изображений, ничего больше. Если я делаю то, что делаю, я получаю больше - позволяя фильтровать, <none>как я здесь. Имеет смысл?
Дирк Эддельбюттель

2

Чтобы удалить помеченные изображения, на которых не запущен контейнер, вам придется использовать небольшой скрипт:

#!/bin/bash

# remove not running containers
docker rm $(docker ps -f "status=exited" -q)

declare -A used_images

# collect images which has running container
for image in $(docker ps | awk 'NR>1 {print $2;}'); do
    id=$(docker inspect --format="{{.Id}}" $image);
    used_images[$id]=$image;
done

# loop over images, delete those without a container
for id in $(docker images --no-trunc -q); do
    if [ -z ${used_images[$id]} ]; then
        echo "images is NOT in use: $id"
        docker rmi $id
    else
        echo "images is in use:     ${used_images[$id]}"
    fi
done

2

Удалите старые контейнеры несколько недель назад.

docker rm $(docker ps -a | grep "weeks" | awk '{ print $1; }')

Удалить старые изображения недель назад. Быть осторожен. Это удалит базовые изображения, которые были созданы несколько недель назад, но которые могут использовать ваши новые изображения.

docker rmi $(docker images | grep 'weeks' | awk '{ print $3; }')


2

Как удалить помеченное изображение

  1. Докер RMI тег первым

  2. Докер RMI изображение.

    # это можно сделать одним вызовом docker rmi, например: # docker rmi <repo: tag> <imageid>

(это работает ноябрь 2016, версия Docker 1.12.2)

например

$ docker images 
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
usrxx/the-application   16112805            011fd5bf45a2        12 hours ago        5.753 GB
usryy/the-application   vx.xx.xx            5af809583b9c        3 days ago          5.743 GB
usrzz/the-application   vx.xx.xx            eef00ce9b81f        10 days ago         5.747 GB
usrAA/the-application   vx.xx.xx            422ba91c71bb        3 weeks ago         5.722 GB
usrBB/the-application   v1.00.18            a877aec95006        3 months ago        5.589 GB

$ docker rmi usrxx/the-application:16112805 && docker rmi 011fd5bf45a2
$ docker rmi usryy/the-application:vx.xx.xx && docker rmi 5af809583b9c
$ docker rmi usrzz/the-application:vx.xx.xx eef00ce9b81f
$ docker rmi usrAA/the-application:vx.xx.xx 422ba91c71bb
$ docker rmi usrBB/the-application:v1.00.18 a877aec95006

Например, сценарий удалить все, что старше 2 недель.

IMAGESINFO=$(docker images --no-trunc --format '{{.ID}} {{.Repository}} {{.Tag}} {{.CreatedSince}}' |grep -E " (weeks|months|years)")
TAGS=$(echo "$IMAGESINFO" | awk '{ print $2 ":" $3 }' )
IDS=$(echo "$IMAGESINFO" | awk '{ print $1 }' )
echo remove old images TAGS=$TAGS IDS=$IDS
for t in $TAGS; do docker rmi $t; done
for i in $IDS; do docker rmi $i; done


1
docker rm `docker ps -aq`

или

docker rm $(docker ps -q -f status=exited)

3
Я думаю, что этот ответ опасен, потому что эти команды удаляют контейнеры. Во-первых, OP спрашивал, как удалить изображения, а не контейнеры. И что более важно, эти команды могут привести к потере данных, поскольку люди могут иметь некоторые ценные данные в вышедших контейнерах.
u.unver34

Вы должны описать потенциально нежелательные результаты применения этих команд на производственном сервере.
Даниил

это удаляет контейнеры, а не изображения.
SEF

1

Иногда я сталкиваюсь с проблемами, когда Docker выделяет и продолжает использовать дисковое пространство, даже если пространство не выделено для какого-либо конкретного образа или существующего контейнера. Последний случай, когда я сгенерировал эту проблему, случайно использовал сборку centos «docker-engine» вместо «docker» в RHEL 7.1. Кажется, что иногда случается, что очистка контейнеров не завершается успешно, и тогда пространство никогда не используется повторно. Когда 80-гигабайтный диск, который я выделил как / был заполнен файлами / var / lib / docker, мне пришлось придумать творческий способ решить проблему.

Вот что я придумал. Сначала устраните ошибку переполнения диска:

  1. Остановить докер: systemctl остановить докер
  2. Выделен новый диск, смонтированный как скажем / mnt / docker.
  3. Переместите все файлы в / var / lib / docker в / mnt / docker. Я использовал команду: rsync -aPHSx --remove-source-files / var / lib / docker / / mnt / docker /
  4. Смонтируйте новый диск в / var / lib / docker.

В этот момент у меня больше не было ошибки переполнения диска, но я все еще тратил огромное количество места. Следующие шаги должны позаботиться об этом.

  1. Запустите Docker: systemctl запустите Docker

  2. Сохраните все изображения: docker save $ (изображения docker | sed -e '/ ^ / d' -e '/ ^ REPOSITORY / d' -e 's, [] [] ,:,' -e 's, [ ]. ,, ')> /root/docker.img

  3. Удалить докер.

  4. Стереть все в / var / lib / docker: rm -rf / var / lib / docker / [cdintv] *

  5. Переустановите докер

  6. Включить докер: systemctl включить докер

  7. Запустить докер: systemctl запустить докер

  8. Восстановление изображений: загрузка докера </root/docker.img

  9. Запустите все постоянные контейнеры, которые вам нужны.

Это уменьшило использование моего диска с 67 ГБ для докера до 6 ГБ для докера.

Я не рекомендую это для повседневного использования. Но полезно запускать, когда похоже, что докер потерял отслеживание использованного дискового пространства из-за программных ошибок или неожиданных перезагрузок.


1

Если вы хотите автоматически / периодически очищать закрытые контейнеры и удалять изображения и тома, которые не используются запущенным контейнером, вы можете загрузить изображение meltwater/docker-cleanup.

Просто беги:

docker run -d -v /var/run/docker.sock:/var/run/docker.sock:rw  -v /var/lib/docker:/var/lib/docker:rw --restart=unless-stopped meltwater/docker-cleanup:latest

Он запускается каждые 30 минут по умолчанию. Однако вы можете установить время задержки, используя этот флаг в секундах (опция DELAY_TIME = 1800).

Более подробная информация: https://github.com/meltwater/docker-cleanup/blob/master/README.md


1

Если вы создаете эти сокращенные образы самостоятельно (из некоторых других, более старых базовых образов), пожалуйста, будьте осторожны с принятыми выше решениями, основанными на том docker image prune, что команда является тупой и постарается удалить также все зависимости, требуемые вашими последними изображениями (команда должна быть вероятно переименован вdocker image*s* prune ).

Решение, которое я нашел для моих конвейеров сборки образа докера (где есть ежедневные сборки и теги = даты в YYYYMMDDформате), заключается в следующем:

# carefully narrow down the image to be deleted (to avoid removing useful static stuff like base images)
my_deleted_image=mirekphd/ml-cpu-py37-vsc-cust

# define the monitored image (tested for obsolescence), which will be usually the same as deleted one, unless deleting some very infrequently built image which requires a separate "clock"
monitored_image=mirekphd/ml-cache

# calculate the oldest acceptable tag (date)
date_week_ago=$(date -d "last week" '+%Y%m%d')

# get the IDs of obsolete tags of our deleted image
# note we use monitored_image to test for obsolescence
my_deleted_image_obsolete_tag_ids=$(docker images --filter="before=$monitored_image:$date_week_ago" | grep $my_deleted_image | awk '{print $3}')

# remove the obsolete tags of the deleted image
# (note it typically has to be forced using -f switch)
docker rmi -f $my_deleted_image_obsolete_tag_ids


0

Первый забег docker images чтобы увидеть список изображений и скопировать ИД ИЗОБРАЖЕНИЯ в буфер обмена.

Запустить docker rmi -f <Image>

Помните, что опция -fпринудительного удаления.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.