Як видалити старі та невикористані зображення Docker


762

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

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

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

Відповіді:


1402

Оновлення вересня 2016 року: Docker 1.13: PR 26108 та зобов’язання 86de7c0 введіть кілька нових команд, щоб полегшити візуалізацію, скільки місця займають дані демона демона на диску та дозволяючи легко очистити "зайві" надлишки.

docker system pruneвидалить ВСІ висячі дані (тобто для того, щоб контейнери зупинені, томи без контейнерів та зображення без контейнерів). Навіть невикористані дані, з -aопцією.

У вас також є:

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

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

Поєднання docker xxx pruneз --filterможливістю може стати прекрасним способом обмежити обрізку ( мінімальну докерну SDK API 1.28 мінімум, тому докер 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-контейнера та зображення сміття для зображень.

  • Контейнери, які вийшли більше години тому, вилучаються.
  • Зображення, які не належать до жодного залишкового контейнера, після цього видаляються.

28
Чи є документація про те, що "dangling=true"насправді означає?
CivFan

1
Цей скрипт не може видалити деякі зображення, витягнуті місяці тому
Quanlong

2
dcleanupдивовижно!
Кванлонг

4
@herm По-перше, docker system pruneвидаляє набагато більше, ніж просто зображення. Обов’язково використовуйте docker image pruneнатомість. І будьте дуже обережні з -a: а docker system prune -aможе мати руйнівний ефект (також видаляючи обсяги). Нарешті, так, -aвидаляє невикористані зображення, я відредагую відповідь.
VonC

2
@stom: "невикористаний" означає "зображення, на які не посилається жоден контейнер, але висячі засоби зовсім не позначені тегами (лише ідентифікатор).
VonC,

124

Оновіть друге (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

Якщо ви проявили надзвичайну обережність щодо безповоротної втрати даних , ви можете видалити невикористані (звисаючі) томи (v1.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яка буде працювати до тих пір, поки ви ніколи не назвете своїх томів чимось подібним до настанови. Я можу змінити це для нового синтаксису фільтра.
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 Для команди видалити старі зображення докера. Це трохи хакітно, але рішення оригінальне і прекрасно працює :)
Rick

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 або новішої, ви можете просто скористатися командами prune. Що стосується конкретного питання щодо видалення старих зображень, ви хочете перше.

# 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
Ви не хочете обрізати невикористані мережі, чи не так? наприклад, якщо всі контейнери будуть зупинені, і я видалю ці мережі, як вони працюватимуть, якщо я їх запускаю. Чи створюються мережі разом із докером?
meffect

@meffect Я повністю погоджуюся і, бог, помітив, що я покинув мережу. Я включив це і додав частину в кінці, вказуючи, що я не рекомендую використовувати, docker system pruneа окремі чорнослив.
Programster

15

Досі (Докер версія 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)
rodvlopes

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 / lib / docker

Цей шлях є локальним для системи, як правило, у кореневому розділі THE, "/" .

Ви можете встановити більший простір на диску та перемістити вміст /var/lib/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 вже дав дуже приємну відповідь, але для повноти ось невеликий сценарій, який я використовую --- і який також запускає будь-які процеси докерів, якщо у вас є такі:

#!/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 }')?
SeF

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. docker rmi тег першим

  2. docker rmi зображення.

    #, що можна зробити в одному дзвінку докера 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
Я думаю, що ця відповідь небезпечна, оскільки ці команди видаляють контейнери. По-перше, ОП запитували, як видалити зображення, а не контейнери. І що ще важливіше, ці команди можуть спричинити втрату даних через те, що люди можуть мати якісь цінні дані у закритих контейнерах.
u.unver34

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

це видаляє контейнери, а не зображення.
SeF

1

Інколи я стикаюся з проблемами, коли Docker виділяє та продовжує використовувати дисковий простір, навіть коли простір не виділяється для якогось конкретного зображення чи наявного контейнера. Останній спосіб, як я випадково створив цю проблему, використовував збірку центрів "docker-engine" замість "докера" в RHEL 7.1. Здається, іноді очищення контейнерів не завершується успішно, і тоді простір ніколи не використовується повторно. Коли диск 80 Гб, який я виділив як / був заповнений файлами / var / lib / docker, мені довелося придумати творчий спосіб вирішити проблему.

Ось що я придумав. Спочатку вирішіть повну помилку диска:

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

У цей момент у мене більше не було повної помилки на диску, але я все-таки витрачав величезну кількість місця. Наступні кроки - це подбати про це.

  1. Запустити докер: systemctl start docker

  2. Збережіть усі зображення: docker save $ (docker images | 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 start docker

  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 щоб переглянути список зображень та скопіюйте IMAGE HASH ID в буфер обміну.

Біжи docker rmi -f <Image>

Варіант запам'ятовування -f- примусове видалення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.