Làm cách nào để lấy danh sách các hình ảnh con phụ thuộc trong Docker?


123

Tôi đang cố xóa một hình ảnh và nhận được:

# 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

Đây là phiên bản docker:

# 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

nhưng không có thêm thông tin:

# 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

Làm cách nào tôi có thể lấy hình ảnh đứa trẻ phụ thuộc mà nó tuyên bố là có?

không có vùng chứa đang chạy hoặc đã dừng với id hình ảnh đó.


9
Tôi phải tự hỏi tại sao nhóm docker không thể cung cấp một cách gốc để làm điều này?
Amalgovinus

Câu trả lời:


54

Câu trả lời ngắn gọn: Đây là một tập lệnh python3 liệt kê các hình ảnh docker phụ thuộc.

Câu trả lời dài: Bạn có thể thấy id hình ảnh và id mẹ cho tất cả hình ảnh được tạo sau hình ảnh được đề cập với thông tin sau:

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

Bạn sẽ có thể tìm kiếm những hình ảnh có id cha bắt đầu bằng f50f9524513f, sau đó tìm kiếm những hình ảnh con của những thứ đó , v.v. Nhưng .Parent không phải như bạn nghĩ. , vì vậy trong hầu hết các trường hợp, bạn cần chỉ định docker images --allở trên để làm cho điều đó hoạt động, sau đó bạn cũng sẽ nhận được id hình ảnh cho tất cả các lớp trung gian.

Đây là một tập lệnh python3 hạn chế hơn để phân tích cú pháp đầu ra của docker và thực hiện tìm kiếm để tạo danh sách hình ảnh:

#!/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))))

Nếu bạn lưu desc.pynó như sau, bạn có thể gọi nó như sau:

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

Hoặc chỉ sử dụng ý chính ở trên , thao tác tương tự.


2
Điều gì sẽ xảy ra nếu không ai trong số họ bắt đầu với các ký tự mong đợi? Điều đó cho thấy một lỗi có thể xảy ra? Tôi đang sử dụng Docker cho Mac beta, FWIW, vì vậy điều đó sẽ không làm tôi ngạc nhiên.
neverfox

Hoặc đó là một lỗi, hoặc nó có nghĩa là hình ảnh được đề cập không có bất kỳ hình ảnh trẻ em nào.
Aryeh Leib Taurog

2
Điều này không thực sự trả lời câu hỏi ban đầu. Điều này cho thấy những gì được tạo ra sau hình ảnh được đề cập, có thể có hoặc không phụ thuộc vào hình ảnh mà người đăng đang cố gắng xóa. Câu trả lời của Simon Brady thực hiện được mẹo, đối với ít nhất là các kích thước mẫu hình ảnh nhỏ.
penguincoder

2
@penguincoder đó là tập lệnh python.
Aryeh Leib Taurog

Giống như @prisfox, câu trả lời này không phù hợp với tôi. Tuy nhiên, câu trả lời của Simon Brady dưới đây đã hoạt động.
Đánh dấu

91

Nếu bạn không có một số lượng lớn hình ảnh, thì luôn có cách tiếp cận bạo lực:

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

1
Tôi nghĩ đây là giải pháp "tốt nhất". Bạn có thể mở rộng này một chút và làm cho nó thêm một chút rõ ràng những gì là những gì bằng cách thay đổi echo $1đến xấu xí (nhưng vẫn tấn công brute-forcy) docker images | grep $i(xách tay hơn trong các phiên bản Docker vì sử dụng --filterlá cờ cho Image Id)
Jon V

15

Cài đặt dockviz và theo dõi các nhánh từ id hình ảnh trong chế độ xem dạng cây:

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

tốt hơn nên làm sudo apt-get update ; sudo apt-get install golang-go; export GOPATH=$HOME/.gotrước.
loretoparisi

3
Có sẵn trên macOS quabrew install dockviz
rcoup

Hãy cẩn thận, khi sử dụng Ubuntu. Nó thường sử dụng các kho lưu trữ lỗi thời để di chuyển
Qohelet

7

Tôi đã tạo một ý chính với shell script để in ra cây con của một hình ảnh docker, nếu bất kỳ ai quan tâm đến giải pháp bash:

#!/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" ""

Mặc dù liên kết này có thể trả lời câu hỏi, nhưng tốt hơn hết bạn nên đưa các phần thiết yếu của câu trả lời vào đây và cung cấp liên kết để tham khảo. Các câu trả lời chỉ có liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi. - Từ đánh giá
Juan Cruz Soler

Tôi chỉ gặp khó khăn định dạng mã, vì vậy tôi đã từ bỏ, nhờ làm Jan này
Michal Linhard

2

Đây là những gì tôi đã làm để lưu giữ "hình ảnh" cuối cùng của mình (thực sự là lớp - đó là thứ đã khiến tôi thất vọng, vì tôi vừa mới bắt đầu xây dựng docker).

Tôi đã nhận được toàn bộ thông báo "... không thể bị ép buộc ...". Tôi nhận ra rằng tôi không thể xóa những hình ảnh mà tôi không cần vì chúng không phải là những hình ảnh thực sự độc lập được tạo bởi 'docker commit'. Vấn đề của tôi là, tôi có một số hình ảnh (hoặc lớp) giữa hình ảnh cơ sở và hình ảnh cuối cùng của tôi và chỉ cần cố gắng dọn dẹp là tôi đã gặp lỗi / cảnh báo về trẻ em và phụ huynh.

  1. Tôi đã xuất hình ảnh cuối cùng (hoặc lớp, nếu bạn muốn) ra một tarball.
  2. Sau đó, tôi đã xóa tất cả những hình ảnh mà tôi muốn, bao gồm cả ảnh cuối cùng của tôi - tôi đã lưu nó vào một tarball, trong khi tôi không chắc mình có thể sử dụng nó hay không, tôi chỉ đang thử nghiệm.
  3. Sau đó tôi chạy docker image load -i FinalImage.tar.gz. Đầu ra giống như:

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 hình ảnh đã tải: sha256: 82d4f8ef9ea1eab72d989455728762ed3c0fe35fd85acf9edc47b41dacfd6382

Bây giờ, khi tôi liệt kê với 'docker image ls', tôi chỉ có hình ảnh gốc ban đầu và hình ảnh cuối cùng trước đây tôi đã lưu vào 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

Hệ thống của tôi hiện 'sạch'. Tôi chỉ có những hình ảnh tôi muốn. Tôi thậm chí đã xóa hình ảnh cơ sở mà không có vấn đề gì.

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

Câu trả lời tốt, nhưng tải chỉ được cho là được sử dụng trên một hình ảnh được tạo từ "docker save".
Khôi

2

Dựa trên câu trả lời slushyMichael Hoffman , nếu bạn không có nhiều hình ảnh, bạn có thể sử dụng hàm shell này:

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}"
}

và sau đó gọi nó bằng cách sử dụng

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

2

Đây là một giải pháp dựa trên API Python ( pip install docker) liệt kê đệ quy các con cháu cùng với các thẻ của chúng (nếu có), tăng thụt lề theo độ sâu của mối quan hệ (con, cháu, v.v.):

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())

Thí dụ:

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

Tôi đã cung cấp nó dưới dạng ý chính tại https://gist.github.com/simleo/10ad923f9d8a2fa410f7ec2d7e96ad57


1

Đây là một cách đơn giản để lấy danh sách các hình ảnh con phụ thuộc vào hình ảnh mẹ:

image_id=123456789012

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

Điều đó sẽ tạo ra một danh sách các ID hình ảnh con / mẹ, chẳng hạn (được cắt ngắn cho ngắn gọn):

sha256:abcdefghijkl sha256:123456789012

Phía bên trái là ID hình ảnh con, phía bên phải là ID hình ảnh cha mẹ mà chúng tôi đang cố gắng xóa, nhưng có thông báo "hình ảnh có hình ảnh con phụ thuộc". Điều này cho chúng ta biết đó abcdefghijkllà đứa trẻ phụ thuộc vào 123456789012. Vì vậy, trước tiên chúng tôi cần docker rmi abcdefghijkl, sau đó bạn có thể docker rmi 123456789012.

Bây giờ, có thể có một chuỗi hình ảnh con phụ thuộc, vì vậy bạn có thể phải tiếp tục lặp lại để tìm con cuối cùng.


0

Bạn có thể xóa hình ảnh Docker bất kể mối quan hệ cha mẹ và con cái thông qua thư mục bên dưới của Docker

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

Trong thư mục này, bạn có thể tìm thấy hình ảnh Docker, vì vậy bạn có thể xóa những gì bạn muốn.


Tôi đang cố gắng thực hiện các lệnh di động bằng cách sử dụng API của docker, giả sử rằng công cụ lập bản đồ thiết bị và công cụ docker (trái ngược với swarm của docker) làm cho điều này trở thành một giải pháp không di động. Cũng có rủi ro khi xóa các tệp trong hệ thống tệp trong khi quá trình khác (bao gồm cả trình nền đế cắm) có thể đang sử dụng nó.
nicocesar 19/12/16

nó ở đâu trên macos?
Anthony Kong

1
* CẢNH BÁO "điều này có thể gây ra nhiều lỗi với việc xóa và kéo vùng chứa trong tương lai. Không bao giờ xóa /var/lib/dockertrực tiếp bằng tay
vladkras 15/1018

0

Làm thế nào về:

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)

Nó sẽ in id hình ảnh con, với sha256:tiền tố.
Tôi cũng có những thứ sau, nối các tên:

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

  • ID= Nhận id đầy đủ của hình ảnh
  • IMAGES= Nhận tất cả hình ảnh con có hình ảnh này được liệt kê là Image
  • echo... Loại bỏ các bản sao và lặp lại kết quả

Tôi thích các điều kiện định dạng Go, nhưng có lẽ chúng tốt hơn như một bộ lọc cho trường hợp sử dụng này.
ingyhere

0

Tôi đã nấu ra điều này để tìm đệ quy con cái, thẻ repo của chúng và in những gì chúng đang làm:

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
}

Đừng quên xóa / tmp / dii- * nếu máy chủ của bạn không an toàn.


-5

Tôi cũng phải đối mặt với vấn đề tương tự. Các bước không được phép bên dưới để giải quyết sự cố.

Dừng tất cả các vùng chứa đang chạy

docker stop $ (docker ps -aq) Xóa tất cả các vùng chứa

docker rm $ (docker ps -aq) Xóa tất cả hình ảnh

docker rmi $ (hình ảnh docker -q)


câu trả lời này không đáp ứng yêu cầu của người hỏi.
Ankur Loriya

Vui lòng ngừng nhận xét những thứ mà mọi người có thể sao chép và dán và làm những điều có hại.
nicocesar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.