プライベートDockerレジストリを実行していますが、以外のすべてのイメージをlatest
リポジトリから削除します。リポジトリ全体を削除するのではなく、リポジトリ内のいくつかの画像を削除します。APIドキュメントは、これを行う方法については言及しませんが、確かにそれは可能ですか?
プライベートDockerレジストリを実行していますが、以外のすべてのイメージをlatest
リポジトリから削除します。リポジトリ全体を削除するのではなく、リポジトリ内のいくつかの画像を削除します。APIドキュメントは、これを行う方法については言及しませんが、確かにそれは可能ですか?
回答:
現在、そのタスクにレジストリ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
ますか?おそらくない!
<version1>
Docker REST APIを使用してタグを削除すると、次のようになります。
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>
これは、あなたの望むことですか?
レジストリで同じ問題に直面した後、ブログページから以下の解決策を試しました。できます。
次のURLを呼び出すことにより、カタログを一覧表示できます。
http://YourPrivateRegistyIP:5000/v2/_catalog
応答は次の形式になります。
{
"repositories": [
<name>,
...
]
}
次のURLを呼び出すことにより、カタログのタグをリストできます。
http://YourPrivateRegistyIP:5000/v2/<name>/tags/list
応答は次の形式になります。
{
"name": <name>,
"tags": [
<tag>,
...
]
}
このコマンドは、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
docker registyコンテナーで次のコマンドを実行します。
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
Deleteing blob: /docker/...
」に関するメッセージを含め、コマンドは成功しましたが、使用されたディスク容量は変更されませんでした。bin / registry github.com/docker/distribution v2.4.1を使用します。
Docker-Content-Digest
一部には、すなわち、小文字(ドッカエンジンv18.09.2でテスト)にする必要があります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)}'
現在の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/
DELETE
です。
{"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported."}]}
問題1
これはプライベートDockerレジストリであるとのことですが、おそらく、提供したリンクであるHubレジストリAPI docではなく、Registry APIを確認する必要があります。
問題2
Dockerレジストリ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"}
registry
画像から画像データを削除する方法を探していました。SSHを使用してスクリプトを実行することは、理想的ではない場合でも機能します。余談ですが、それでも不完全なAPIだと思います。タグを削除することはできますが、GETし/images
ても残りの画像データはすべて表示されます。
これは本当に醜いですが、動作します。テキストはレジストリ:2.5.1でテストされます。削除を有効にする構成を更新した後でも、削除をスムーズに機能させることができませんでした。IDを取得するのは非常に難しく、ログインするにはIDを取得する必要がありました。とにかく、次の作品:
コンテナにログイン
docker exec -it registry sh
コンテナーとコンテナーのバージョンに一致する変数を定義します。
export NAME="google/cadvisor"
export VERSION="v0.24.1"
レジストリディレクトリに移動します。
cd /var/lib/registry/docker/registry/v2
ハッシュに関連するファイルを削除します。
find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
マニフェストを削除します。
rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
ログアウト
exit
GCを実行します。
docker exec -it registry bin/registry garbage-collect /etc/docker/registry/config.yml
すべてが適切に行われた場合、削除されたblobに関する情報が表示されます。
正確にそれを行ういくつかのクライアント(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
更新:これはdeckschrubberの短い紹介です。
deckschrubber
非常に優れています-インストールが非常に簡単で(シングルバイナリ)、名前(正規表現の一致)と年齢でイメージを削除できます。
ERRO[0000] Could not delete image! repo=.... tag=latest
:/
簡単に。
1)docker repoのRepoDigestsに対して次のコマンドを入力する必要があります。
## docker inspect <registry-host>:<registry-port>/<image-name>:<tag>
> docker inspect 174.24.100.50:8448/example-image:latest
[
{
"Id": "sha256:16c5af74ed970b1671fe095e063e255e0160900a0e12e1f8a93d75afe2fb860c",
"RepoTags": [
"174.24.100.50:8448/example-image:latest",
"example-image:latest"
],
"RepoDigests": [
"174.24.100.50:8448/example-image@sha256:5580b2110c65a1f2567eeacae18a3aec0a31d88d2504aa257a2fecf4f47695e6"
],
...
...
$ {digest} = sha256:5580b2110c65a1f2567eeacae18a3aec0a31d88d2504aa257a2fecf4f47695e6
2)レジストリREST APIを使用する
##curl -u username:password -vk -X DELETE registry-host>:<registry-port>/v2/<image-name>/manifests/${digest}
>curl -u example-user:example-password -vk -X DELETE http://174.24.100.50:8448/v2/example-image/manifests/sha256:5580b2110c65a1f2567eeacae18a3aec0a31d88d2504aa257a2fecf4f47695e6
呼び出しを成功させるには、202 Acceptedを取得する必要があります。
3-)ガベージコレクターの実行
docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml
レジストリ —レジストリコンテナ名。
詳細な説明については、リンクの説明をここに入力してください
このDockerイメージには、リモートv2レジストリからイメージを削除するために使用できるbashスクリプトが含まれています。https: //hub.docker.com/r/vidarl/remove_image_from_registry/
以下の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
この回答に基づく単純なrubyスクリプト:registry_cleaner。
ローカルマシンで実行できます。
./registry_cleaner.rb --host=https://registry.exmpl.com --repository=name --tags_count=4
次に、レジストリマシンでを使用してblobを削除し/bin/registry garbage-collect /etc/docker/registry/config.yml
ます。
これは、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