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.