Docker에서 종속 자식 이미지 목록을 가져 오는 방법은 무엇입니까?


123

이미지를 제거하려고하는데 다음과 같은 결과가 나타납니다.

# docker rmi f50f9524513f  
Failed to remove image (f50f9524513f): Error response from daemon: conflict: unable to delete f50f9524513f (cannot be forced) - image has dependent child images

이것은 도커 버전입니다.

# docker version
Client:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 21:49:11 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 21:49:11 2016
 OS/Arch:      linux/amd64

그러나 추가 정보는 없습니다.

# docker images --format="raw" | grep f50f9524513f -C3

repository: debian
tag: 8
image_id: f50f9524513f
created_at: 2016-03-01 18:51:14 +0000 UTC
virtual_size: 125.1 MB

repository: debian
tag: jessie
image_id: f50f9524513f
created_at: 2016-03-01 18:51:14 +0000 UTC
virtual_size: 125.1 MB

가지고 있다고 주장 하는 종속 자식 이미지를 어떻게 얻을 수 있습니까?

해당 이미지 ID로 실행 중이거나 중지 된 컨테이너가 없습니다.


9
도커 팀이이 작업을 수행하는 기본 방법을 제공 할 수없는 이유가 궁금합니다.
— Amalgovinus

답변:


54

짧은 대답 : 다음은 종속 된 도커 이미지를 나열 하는 python3 스크립트 입니다.

긴 답변 : 다음과 같이 문제의 이미지 뒤에 생성 된 모든 이미지의 이미지 ID와 상위 ID를 볼 수 있습니다.

docker inspect --format='{{.Id}} {{.Parent}}' \
    $(docker images --filter since=f50f9524513f --quiet)

부모 ID가 f50f9524513f로 시작하는 이미지를 찾은 다음 해당 이미지 등 의 자식 이미지를 찾을 수 있어야합니다 . 하지만 .Parent 생각하는 것은 아닙니다. , 따라서 대부분의 경우 docker images --all해당 작업을 수행하려면 위에서 지정해야하며 , 그러면 모든 중간 레이어에 대한 이미지 ID도 얻게됩니다.

다음은 docker 출력을 구문 분석하고 이미지 목록을 생성하기 위해 검색을 수행하는보다 제한된 python3 스크립트입니다.

#!/usr/bin/python3
import sys

def desc(image_ids, links):
    if links:
        link, *tail = links
        if len(link) > 1:
            image_id, parent_id = link
            checkid = lambda i: parent_id.startswith(i)
            if any(map(checkid, image_ids)):
                return desc(image_ids | {image_id}, tail)
        return desc(image_ids, tail)
    return image_ids


def gen_links(lines):
    parseid = lambda s: s.replace('sha256:', '')
    for line in reversed(list(lines)):
        yield list(map(parseid, line.split()))


if __name__ == '__main__':
    image_ids = {sys.argv[1]}
    links = gen_links(sys.stdin.readlines())
    trunc = lambda s: s[:12]
    print('\n'.join(map(trunc, desc(image_ids, links))))

이것을 저장하면 desc.py다음과 같이 호출 할 수 있습니다.

docker images \
    | fgrep -f <(docker inspect --format='{{.Id}} {{.Parent}}' \
        $(docker images --all --quiet) \
        | python3 desc.py f50f9524513f )

또는 위의 요점을 사용 하여 동일한 작업을 수행하십시오.


2
그들 중 어느 것도 예상 문자로 시작하지 않으면 어떻게 될까요? 그것은 가능한 버그를 나타 냅니까? 저는 Docker for Mac 베타, FWIW를 사용하고 있으므로 놀라지 않을 것입니다.
— neverfox

버그이거나 문제의 이미지에 자식이 없음을 의미합니다.
— Aryeh Leib Taurog

2
이것은 원래 질문에 실제로 대답하지 않습니다. 이것은 문제의 이미지 다음에 생성 된 것을 보여 주며, 포스터가 삭제하려고했던 이미지에 의존 할 수도 있고 아닐 수도 있습니다. Simon Brady의 대답은 최소한 작은 샘플 크기의 이미지에 대해 트릭을 수행합니다.
— penguincoder

2
@penguincoder는 파이썬 스크립트의 용도입니다.
— Aryeh Leib Taurog

@neverfox와 마찬가지로이 답변은 저에게 효과적이지 않았습니다. 아래의 Simon Brady의 대답은 효과가있었습니다.
— Mark

91

이미지 수가 많지 않은 경우 항상 무차별 대입 방식이 있습니다.

for i in $(docker images -q)
do
    docker history $i | grep -q f50f9524513f && echo $i
done | sort -u

1
이것이 "최상의"솔루션이라고 생각합니다. 당신은 이것을 조금 확장 echo $1하고 더 추악한 (그러나 여전히 무차별적인) docker images | grep $i( --filter이미지 ID에 플래그를 사용하는 것보다 도커 버전에서 더 이식 가능함) 으로 변경함으로써 무엇이 무엇인지 좀 더 명확하게 만들 수 있습니다.
— Jon V

15

dockviz를 설치 하고 트리보기의 이미지 ID에서 분기를 따릅니다.

go get github.com/justone/dockviz
$(go env GOPATH)/bin/dockviz images --tree -l

sudo apt-get update ; sudo apt-get install golang-go; export GOPATH=$HOME/.go먼저하는 것이 좋습니다 .
— loretoparisi

3
macOS에서 사용 가능brew install dockviz
— rcoup

Ubuntu를 사용할 때주의하십시오. 일반적으로 go를 위해 오래된 저장소를 사용합니다
— Qohelet

7

누구나 bash 솔루션에 관심이있는 경우 Docker 이미지의 하위 트리를 인쇄하기 위해 쉘 스크립트로 요점 을 만들었습니다 .

#!/bin/bash
parent_short_id=$1
parent_id=`docker inspect --format '{{.Id}}' $1`

get_kids() {
    local parent_id=$1
    docker inspect --format='ID {{.Id}} PAR {{.Parent}}' $(docker images -a -q) | grep "PAR ${parent_id}" | sed -E "s/ID ([^ ]*) PAR ([^ ]*)/\1/g"
}

print_kids() {
    local parent_id=$1
    local prefix=$2
    local tags=`docker inspect --format='{{.RepoTags}}' ${parent_id}`
    echo "${prefix}${parent_id} ${tags}"

    local children=`get_kids "${parent_id}"`

    for c in $children;
    do
        print_kids "$c" "$prefix  "
    done
}

print_kids "$parent_id" ""

이 링크가 질문에 답할 수 있지만 여기에 답변의 필수 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 무효화 될 수 있습니다. - 리뷰에서
— Juan Cruz Soler

내가 포기 그래서 난 그냥이 월 일에 대한 감사 문제가 코드를 포맷했다
— 마이클 Linhard

2

이것이 제가 최종 "이미지"를 보존하기 위해 한 일입니다 (레이어, 실제로-제가 방금 도커 빌드에 들어가면서 저를 버렸습니다).

나는 전체 "... 강제 될 수 없다 ..."라는 메시지를 받고 있었다. 필요하지 않은 이미지는 'docker commit'에 의해 생성 된 독립적 인 이미지가 아니기 때문에 삭제할 수 없다는 것을 깨달았습니다. 내 문제는 기본 이미지와 최종 이미지 사이에 여러 이미지 (또는 레이어)가 있었고 정리하려고 시도했을 때 자식과 부모에 대한 오류 / 경고가 발생했습니다.

  1. 최종 이미지 (또는 레이어)를 tarball로 내보냈습니다.
  2. 그런 다음 최종 이미지를 포함하여 원하는 모든 이미지를 삭제했습니다. 타르볼에 저장했기 때문에 사용할 수 있을지 확신 할 수 없었지만 실험 중이었습니다.
  3. 나는 그 다음 달렸다 docker image load -i FinalImage.tar.gz. 출력은 다음과 같습니다.

7d9b54235881: Loading layer [==================================================>]  167.1MB/167.1MB
c044b7095786: Loading layer [==================================================>]  20.89MB/20.89MB
fe94dbd0255e: Loading layer [==================================================>]  42.05MB/42.05MB
19abaa1dc0d4: Loading layer [==================================================>]  37.96MB/37.96MB
4865d7b6fdb2: Loading layer [==================================================>]  169.6MB/169.6MB
a0c115c7b87c: Loading layer [==================================================>]    132MB/132MB

로드 된 이미지 ID : sha256 : 82d4f8ef9ea1eab72d989455728762ed3c0fe35fd85acf9edc47b41dacfd6382

이제 'docker image ls'로 나열하면 원본 기본 이미지와 이전에 tarball에 저장 한 최종 이미지 만 있습니다.

[root@docker1 ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
httpd               import              82d4f8ef9ea1        3 days ago          747MB
centos              httpd               36540f359ca3        5 weeks ago         193MB

내 시스템은 이제 '깨끗'합니다. 원하는 이미지 만 있습니다. 문제없이 기본 이미지도 삭제했습니다.

[root@docker1 ~]# docker rmi 36540f359ca3
Untagged: centos:httpd
Untagged:     centos@sha256:c1010e2fe2b635822d99a096b1f4184becf5d1c98707cbccae00be663a9b9131
Deleted: sha256:36540f359ca3b021d4b6a37815e9177b6c2bb3817598979ea55aee7ecc5c2c1f

좋은 대답이지만로드는 "docker save"에서 생성 된 이미지에만 사용되어야합니다. "docker 내보내기"에 대한 적절한 복원은 "docker import"입니다.
— Amalgovinus

2

를 기반으로 녹은 와 마이클 호프만 당신이 쉘 기능을 사용할 수있는 이미지의 톤이없는 경우, 답변 :

docker_image_desc() {
  for image in $(docker images --quiet --filter "since=${1}"); do
    if [ $(docker history --quiet ${image} | grep ${1}) ]; then
      docker_image_desc "${image}"
    fi
  done
  echo "${1}"
}

다음을 사용하여 호출하십시오.

docker_image_desc <image-id> | awk '!x[$0]++'

2

다음 pip install docker은 태그 (있는 경우)와 함께 하위 항목을 재귀 적으로 나열하여 관계 (자녀, 손자 등)의 깊이에 따라 들여 쓰기를 늘리는 Python API ( ) 기반 솔루션입니다 .

import argparse
import docker

def find_img(img_idx, id):
    try:
        return img_idx[id]
    except KeyError:
        for k, v in img_idx.items():
            if k.rsplit(":", 1)[-1].startswith(id):
                return v
    raise RuntimeError("No image with ID: %s" % id)

def get_children(img_idx):
    rval = {}
    for img in img_idx.values():
        p_id = img.attrs["Parent"]
        rval.setdefault(p_id, set()).add(img.id)
    return rval

def print_descendants(img_idx, children_map, img_id, indent=0):
    children_ids = children_map.get(img_id, [])
    for id in children_ids:
        child = img_idx[id]
        print(" " * indent, id, child.tags)
        print_descendants(img_idx, children_map, id, indent=indent+2)

def main(args):
    client = docker.from_env()
    img_idx = {_.id: _ for _ in client.images.list(all=True)}
    img = find_img(img_idx, args.id)
    children_map = get_children(img_idx)
    print_descendants(img_idx, children_map, img.id)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("id", metavar="IMAGE_ID")
    main(parser.parse_args())

예:

$ python find_dep_img.py 549afbf12931
 sha256:913d0981fdc7d2d673f2c8135b7afd32ba5037755e89b00432d3460422ba99b9 []
   sha256:0748dbc043b96ef9f88265c422e0267807f542e364b7a7fadf371ba5ee082b5d []
     sha256:6669414d2a0cc31b241a1fbb00c0ca00fa4dc4fa65dffb532bac90d3943d6a0a []
       sha256:a6441e7d9e92511608aad631f9abe8627033de41305c2edf7e03ee36f94f0817 ['foo/bar:latest']

https://gist.github.com/simleo/10ad923f9d8a2fa410f7ec2d7e96ad57 에서 요점으로 사용할 수 있도록했습니다.


1

다음은 상위 이미지에 종속 된 하위 이미지 목록을 가져 오는 간단한 방법입니다.

image_id=123456789012

docker images -a -q --filter since=$image_id |
xargs docker inspect --format='{{.Id}} {{.Parent}}' |
grep $image_id

예를 들어 하위 / 부모 이미지 ID 목록이 생성됩니다 (간결성을 위해 잘림).

sha256:abcdefghijkl sha256:123456789012

왼쪽은 하위 ​​이미지 ID이고 오른쪽은 삭제하려는 상위 이미지 ID이지만 "이미지에 종속 하위 이미지가 있습니다."라는 메시지가 표시됩니다. 이것은에 abcdefghijkl의존하는 아이임을 알려줍니다 123456789012. 우리가 처음에 필요 그래서 docker rmi abcdefghijkl, 당신은 할 수 있습니다 docker rmi 123456789012.

이제 종속 자식 이미지 체인이있을 수 있으므로 마지막 자식을 찾기 위해 계속 반복해야 할 수 있습니다.


0

Docker의 아래 디렉토리를 통해 부모 및 자식 관계에 관계없이 Docker 이미지를 삭제할 수 있습니다.

/var/lib/docker/image/devicemapper/imagedb/content/sha256

이 디렉토리에서 Docker 이미지를 찾을 수 있으므로 원하는 것을 삭제할 수 있습니다.


장치 매퍼 및 도커 엔진 (예 : docker swarm과 반대)이이를 휴대용 솔루션으로 만든다고 가정하고 도커 API를 사용하여 이식 가능한 명령을 만들려고합니다. 또한 다른 프로세스 (도커 데몬 포함)가이를 사용할 수있는 동안 파일 시스템에서 파일을 삭제하는 것은 위험합니다.
— nicocesar

macOS에서 어디에 있습니까?
— Anthony Kong

1
* 경고 "이것은 삭제하고 미래에 컨테이너를 끌어 여러 오류가 발생할 수 있습니다 절대로 삭제 DIRS을에. /var/lib/docker직접 손으로
— vladkras

0

어때 :

ID=$(docker inspect --format="{{.Id}}" "$1")
IMAGES=$(docker inspect --format="{{if eq \"$ID\" .Config.Image}}{{.Id}}{{end}}" $(docker images --filter since="$ID" -q))
echo $(printf "%s\n" "${IMAGES[@]}" | sort -u)

sha256:접두사 와 함께 자식 이미지 ID를 인쇄합니다 .
이름을 추가하는 다음도 있습니다.

IMAGES=$(docker inspect --format="{{if eq \"$ID\" .Config.Image}}{{.Id}}{{.RepoTags}}{{end}}" $(docker images --filter since="$ID" -q))

  • ID= 이미지의 전체 ID를 가져옵니다.
  • IMAGES= 이 이미지가 나열된 모든 하위 이미지를 가져옵니다. Image
  • echo... 중복을 제거하고 결과를 에코

나는 Go 형식 조건을 좋아하지만 아마도이 사용 사례의 필터로 더 좋을 것입니다.
— ingyhere

0

나는 이것을 재귀 적으로 아이들과 그들의 repo 태그를 찾고 그들이하고있는 것을 인쇄하기 위해 요리했다.

docker_img_tree() {
    for i in $(docker image ls -qa) ; do
        [ -f "/tmp/dii-$i"  ] || ( docker image inspect $i > /tmp/dii-$i)
        if grep -qiE 'Parent.*'$1 /tmp/dii-$i ; then
            echo "$2============= $i (par=$1)"
            awk '/(Cmd|Repo).*\[/,/\]/' /tmp/dii-$i | sed "s/^/$2/"
            docker_img_tree $i $2===
        fi
    done
}

호스트가 안전하지 않은 경우 / tmp / dii- *를 삭제하는 것을 잊지 마십시오.


-6

나도 같은 문제에 직면했습니다. 문제를 해결하려면 아래 단계를 따르세요.

실행중인 모든 컨테이너 중지

docker stop $ (docker ps -aq) 모든 컨테이너 제거

docker rm $ (docker ps -aq) 모든 이미지 제거

도커 rmi $ (도커 이미지 -q)


이 답변은 질문자 요구 사항을 충족하지 않습니다.
— Ankur Loriya

사람들이 잠재적으로 복사하여 붙여 넣거나 해로운 일을 할 수있는 내용에 대해서는 댓글을 달지 마십시오.
— nicocesar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.