web-dev-qa-db-ja.com

プライベートdockerレジストリから画像を削除する方法?

私は専用のdockerレジストリを実行していて、リポジトリからlatest以外のすべての画像を削除したいのです。リポジトリ全体を削除するのではなく、その中の一部の画像だけを削除します。 APIドキュメント はこれを行う方法について言及していませんが、確かに可能ですか?

121
Leo

現時点では、そのタスクにレジストリAPIを使用することはできません。リポジトリまたは特定のタグを削除することしかできません。

一般に、リポジトリを削除すると、このリポジトリに関連付けられているすべてのタグが削除されます。

タグを削除するとは、画像とタグとの関連付けが削除されることを意味します。

上記のどれも単一の画像を削除しません。それらはあなたのディスクに残されています。


Workaround

この回避策のためにあなたはあなたのdockerイメージをローカルに保存させる必要があります。

この問題を回避するには、最新のタグを除くすべてのタグを削除して、関連する画像への参照を削除することが考えられます。その後、このスクリプトを実行して、タグや他の使用済みイメージの祖先によって参照されていないすべてのイメージを削除できます。 。

用語(画像とタグ)

次のようなイメージグラフを考えてみましょう。大文字(AB、...)は短いイメージIDを表し、<-はイメージが別のイメージに基づいていることを意味します。

 A <- B <- C <- D

今、私たちは写真にタグを追加します。

 A <- B <- C <- D
           |    |
           |    <version2>
           <version1>

ここで、タグ<version1>はイメージCを参照し、タグ<version2>はイメージDを参照します。

あなたの質問を洗練する

あなたの質問では、削除したいと言っていました

latest以外のすべての画像

。さて、この用語はまったく正しくありません。画像とタグが混在しています。グラフを見ると、タグ<version2>が最新のバージョンを表していることに同意すると思います。実際、 この質問によると 最新のバージョンを表すタグを付けることができます。

 A <- B <- C <- D
           |    |
           |    <version2>
           |    <latest>
           <version1>

<latest>タグはimage Dを参照しているので、私はあなたに尋ねます:あなたは本当にimage D以外のすべてを削除したいですか?おそらくそうではありません!

タグを削除するとどうなりますか?

Docker REST AP​​Iを使用してタグ<version1>を削除すると、次のようになります。

 A <- B <- C <- D
                |
                <version2>
                <latest>

覚えておいてください:Dockerは決して画像を削除しません!たとえそうであっても、この場合それはイメージを削除することができません、なぜならイメージCはタグ付けされたイメージDのための先祖の一部であるからです。

このスクリプトを使用しても、画像は削除されません。

画像を削除できるとき

誰かがあなたのレジストリに引っ張ったりプッシュしたりできるときを制御できるという条件の下で(例えばRESTインターフェースを無効にすることによって)。他の画像がそれに基づいておらず、タグがそれを参照していない場合は、画像グラフから画像を削除できます。

次のグラフでは、イメージDは、CではなくBに基づいてnotになっています。したがって、DCに依存しません。このグラフのタグ<version1>を削除すると、画像Cはどの画像でも使用されなくなり、このスクリプトでそれを削除できます。 。

 A <- B <--------- D
      \            |
       \           <version2>
        \          <latest>
         \ <- C
              |
              <version1>

クリーンアップ後、画像グラフは次のようになります。

 A <- B <- D
           |
           <version2>
           <latest>

これは、あなたの望むことですか?

93
Konrad Kleine

私は私の登録簿との同じ問題に直面したそして私はブログページからの下にリストされている解決を試みた。できます。

ステップ1:カタログのリスト

次のURLを呼び出してカタログを一覧表示できます。

http://YourPrivateRegistyIP:5000/v2/_catalog

応答は次の形式になります。

{
  "repositories": [
    <name>,
    ...
  ]
}

ステップ2:関連カタログのタグを一覧表示する

このURLを呼び出すことでカタログのタグを一覧表示できます。

http://YourPrivateRegistyIP:5000/v2/<name>/tags/list

応答は次の形式になります。

{
"name": <name>,
"tags": [
    <tag>,
    ...
]

}

ステップ3:関連タグのマニフェスト値を一覧表示する

このコマンドはdockerレジストリコンテナで実行できます。

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://localhost:5000/v2/<name>/manifests/<tag> 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}'

応答は次の形式になります。

sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

マニフェスト値を指定して以下のコマンドを実行します。

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/<name>/manifests/sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

ステップ4:マークされたマニフェストを削除する

Docker registy containerでこのコマンドを実行してください。

bin/registry garbage-collect  /etc/docker/registry/config.yml  

これが私のconfig.ymlです。

root@c695814325f4:/etc# cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
  service: registry
storage:
    cache:
        blobdescriptor: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
    delete:
        enabled: true
http:
    addr: :5000
    headers:
        X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
46
Yavuz Sert

現在のv2レジストリはDELETE /v2/<name>/manifests/<reference>による削除をサポートするようになりました

参照: https://github.com/docker/distribution/blob/master/docs/spec/api.md#deleting-an-image

実用的な使用法: https://github.com/byrnedo/docker-reg-tool

編集:上記のマニフェスト<reference>は、リクエストから取得することができます

GET /v2/<name>/manifests/<tag>

レスポンスのDocker-Content-Digestヘッダをチェックする。

44
byrnedo

問題1

あなたはそれがあなたのプライベートdockerレジストリであると述べたので、あなたはおそらく レジストリAPI の代わりに ハブレジストリAPIドキュメントをチェックする必要があります 、あなたが提供したリンクです。

問題2

docker registry APIはクライアント/サーバープロトコルであり、バックエンドでイメージを削除するかどうかはサーバーの実装次第です。 (私は推測する)

DELETE /v1/repositories/(namespace)/(repository)/tags/(tag*)

詳細説明

以下に私はあなたの質問に対する私の理解としてあなたの説明からそれが今どのように機能するかを実演します。

あなたは私のデフォルトのものを使い、5000ポートでリッスンします。

docker run -d -p 5000:5000 registry

それから私はローカル画像にタグを付けてそれにプッシュします。

$ docker tag ubuntu localhost:5000/ubuntu
$ docker Push localhost:5000/ubuntu
The Push refers to a repository [localhost:5000/ubuntu] (len: 1)
Sending image list
Pushing repository localhost:5000/ubuntu (1 tags)
511136ea3c5a: Image successfully pushed
d7ac5e4f1812: Image successfully pushed
2f4b4d6a4a06: Image successfully pushed
83ff768040a0: Image successfully pushed
6c37f792ddac: Image successfully pushed
e54ca5efa2e9: Image successfully pushed
Pushing tag for rev [e54ca5efa2e9] on {http://localhost:5000/v1/repositories/ubuntu/tags/latest}

その後、Registry APIを使用して、プライベートdockerレジストリに存在することを確認できます。

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags
{"latest": "e54ca5efa2e962582a223ca9810f7f1b62ea9b5c3975d14a5da79d3bf6020f37"}

そのAPIを使ってタグを削除することができます。

$ curl -X DELETE localhost:5000/v1/repositories/ubuntu/tags/latest
true

もう一度確認してください。タグがプライベートレジストリサーバーに存在しません

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags/latest
{"error": "Tag not found"}
15
Larry Cai

これは本当に醜いですが、うまくいきます、テキストはレジストリでテストされます:2.5.1。削除を有効にするように設定を更新した後でも、削除が円滑に機能しませんでした。 IDを取得するのは本当に難しかったし、それを取得するにはログインしなければならなかった、多少の誤解もありました。とにかく、次のように動作します。

  1. コンテナにログインする

    docker exec -it registry sh
    
  2. コンテナとコンテナのバージョンに一致する変数を定義します。

    export NAME="google/cadvisor"
    export VERSION="v0.24.1"
    
  3. レジストリディレクトリに移動します。

    cd /var/lib/registry/docker/registry/v2
    
  4. ハッシュに関連するファイルを削除します。

    find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
    
  5. マニフェストを削除します。

    rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
    
  6. ログアウト

    exit
    
  7. GCを実行します。

    docker exec -it registry  bin/registry garbage-collect  /etc/docker/registry/config.yml
    
  8. すべてが正しく行われた場合は、削除されたBLOBに関する情報が表示されます。

11
hirro

まさにそれを行うクライアントがいくつかあります(Python、Rubyなど)。私の好みでは、私のレジストリにハウスキーピングするためだけに、ランタイム(例えばPython)を私のレジストリサーバーにインストールすることは持続可能ではありません!


だから deckschrubber が私の解決策です。

go get github.com/fraunhoferfokus/deckschrubber
$GOPATH/bin/deckschrubber

指定した年齢より古い画像は自動的に削除されます。年齢は-year-month-day、またはそれらの組み合わせを使用して指定できます。

$GOPATH/bin/deckschrubber -month 2 -day 13 -registry http://registry:5000

UPDATEこれがdeckschrubberの簡単な紹介 です。

8
Yan Foto

this に基づく単純なRubyスクリプト: registry_cleaner

あなたはローカルマシンでそれを実行することができます:

./registry_cleaner.rb --Host=https://registry.exmpl.com --repository=name --tags_count=4

その後、レジストリマシンで/bin/registry garbage-collect /etc/docker/registry/config.ymlを使用してBLOBを削除します。

0
Ilya Krigouzov

Bashスクリプトの下最新のものを除くレジストリにあるすべてのタグを削除します。

for D in /registry-data/docker/registry/v2/repositories/*; do
if [ -d "${D}" ]; then
    if [ -z "$(ls -A ${D}/_manifests/tags/)" ]; then
        echo ''
    else
        for R in $(ls -t ${D}/_manifests/tags/ | tail -n +2); do
            digest=$(curl -k -I -s -H -X GET http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/${R} -H 'accept: application/vnd.docker.distribution.manifest.v2+json'  | grep Docker-Content-Digest | awk '{print $2}' )
            url="http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/$digest"
            url=${url%$'\r'}
            curl -X DELETE -k -I -s   $url -H 'accept: application/vnd.docker.distribution.manifest.v2+json' 
        done
    fi
fi
done

このランの後

docker exec $(docker ps | grep registry | awk '{print $1}') /bin/registry garbage-collect /etc/docker/registry/config.yml
0
Shree Tiwari

このdockerイメージには、リモートv2レジストリからイメージを削除するために使用できるbashスクリプトが含まれています。 https://hub.docker.com/r/vidarl/remove_image_from_registry/

0
Vidar Langseid