latest
プライベート Docker レジストリを実行していますが、リポジトリ以外のすべてのイメージを削除したいと考えています。リポジトリ全体を削除するのではなく、その中のイメージの一部だけを削除したくありません。API ドキュメントはこれを行う方法について言及していませんが、確かに可能ですか?
15 に答える
現在、そのタスクにレジストリ API を使用することはできません。リポジトリまたは特定のタグのみを削除できます。
通常、リポジトリを削除すると、このリポジトリに関連付けられているすべてのタグが削除されます。
タグの削除とは、画像とタグの関連付けが削除されることを意味します。
上記のいずれも、単一の画像を削除しません。それらはディスクに残ります。
回避策
この回避策では、Docker イメージをローカルに保存する必要があります。
ソリューションの回避策は、最新のタグを除くすべてを削除することです。これにより、関連する画像への参照が削除される可能性があります。次に、このスクリプトを実行して、タグまたは使用されている画像の祖先によって参照されていないすべての画像を削除できます。
用語(画像とタグ)
次のようなイメージ グラフを考えてみましょう。大文字 ( A
、B
、 ...) は短いイメージ 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>
これは、あなたの望むことですか?
現在の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/
問題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"}
これは、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