219

latestプライベート Docker レジストリを実行していますが、リポジトリ以外のすべてのイメージを削除したいと考えています。リポジトリ全体を削除するのではなく、その中のイメージの一部だけを削除したくありません。API ドキュメントはこれを行う方法について言及していませんが、確かに可能ですか?

4

15 に答える 15

136

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

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

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

上記のいずれも、単一の画像を削除しません。それらはディスクに残ります。


回避策

この回避策では、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>タグは画像を参照しているため、画像D以外を本当に削除しますDか? おそらくそうではありません!

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

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

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

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

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

画像を削除できる場合

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

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

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

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

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

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

于 2014-08-28T14:20:26.940 に答える
83

現在の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応答のヘッダーを確認します。

編集 2: 次の環境セットを使用してレジストリを実行する必要がある場合があります。

REGISTRY_STORAGE_DELETE_ENABLED="true"

Edit3: このディスク領域を解放するには、ガベージ コレクションを実行する必要がある場合があります: https://docs.docker.com/registry/garbage-collection/

于 2016-04-28T14:40:39.390 に答える
19

問題1

あなたはそれがあなたのプライベートdockerレジストリであると述べたので、おそらくあなたが提供したリンクであるHub registry API docの代わりにRegistry APIを確認する必要があります。

問題 2

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

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

詳細な説明

以下では、あなたの質問に対する私の理解として、あなたの説明からどのように機能するかをデモします。

プライベート Docker レジストリを実行しています。デフォルトのものを使用し、ポートでリッスンします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}

その後、レジストリ 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"}
于 2014-08-22T00:52:43.573 に答える
0

これは、Yavuz Sert の回答に基づくスクリプトです。最新バージョンではなく、タグが 950 を超えているすべてのタグを削除します。

#!/usr/bin/env bash


CheckTag(){
    Name=$1
    Tag=$2

    Skip=0
    if [[ "${Tag}" == "latest" ]]; then
        Skip=1
    fi
    if [[ "${Tag}" -ge "950" ]]; then
        Skip=1
    fi
    if [[ "${Skip}" == "1" ]]; then
        echo "skip ${Name} ${Tag}"
    else
        echo "delete ${Name} ${Tag}"
        Sha=$(curl -v -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://127.0.0.1:5000/v2/${Name}/manifests/${Tag} 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}')
        Sha="${Sha/$'\r'/}"
        curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE "http://127.0.0.1:5000/v2/${Name}/manifests/${Sha}"
    fi
}

ScanRepository(){
    Name=$1
    echo "Repository ${Name}"
    curl -s http://127.0.0.1:5000/v2/${Name}/tags/list | jq '.tags[]' |
    while IFS=$"\n" read -r line; do
        line="${line%\"}"
        line="${line#\"}"
        CheckTag $Name $line
    done
}


JqPath=$(which jq)
if [[ "x${JqPath}" == "x" ]]; then
  echo "Couldn't find jq executable."
  exit 2
fi

curl -s http://127.0.0.1:5000/v2/_catalog | jq '.repositories[]' |
while IFS=$"\n" read -r line; do
    line="${line%\"}"
    line="${line#\"}"
    ScanRepository $line
done
于 2020-07-01T10:26:08.173 に答える