サーバー上で実行されているDockerコンテナーの束があり、「最新の」タグを使用するか、すべてのタグにタグを使用しませんでした。ここで、イメージのバージョンをフリーズしたいのですが、これらのイメージをいつプルしたかわからないため、「最新」がどのバージョンを指しているのかわかりません。 docker ps
は、コンテナが次のように「最新」のタグを使用しているか、タグを使用していないことを示しています。
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
371d6675888b node:latest "npm start" 6 days ago Up 2 hours project_xyz_1
ca5a75425a34 Selenium/node-chrome "/usr/bin/Nohup go..." 6 days ago Up 2 hours project_xyz-chrome_1
...
私が使用するすべての画像は、Dockerハブからの公開画像です。
Docker psが表示する16進数のIDをすべてのコンテナーに使用できると思いましたが、IDはコンテナーIDであり、イメージIDではないことに気付きました。
実行中のすべてのコンテナのイメージID /ハッシュを取得し、一致するすべてのタグをスキャンすることなどは可能ですか?
Dockerバージョン:18.09.1、ビルド4c52b90
編集:
したがって、画像のID(ダイジェスト)を取得する方法を示すいくつかの回答がありましたが、それらの画像の実際のタグを何らかの方法で見つける必要があります。調査の結果、DockerハブにはAPIがあり、特定の画像のすべてのタグを取得する方法と、特定の画像+タグのダイジェストを取得する方法があることがわかりました。 APIとstackoverflowからの多くの例を見て、これを思いつきました(以下の回答から、ローカルイメージのダイジェストを取得するために必要なコードも含まれています)。
function getDigestByImageNameWithTag () {
TARGET_IMAGE_NAME_WITH_TAG="$1" # works with and without tag
docker image inspect --format '{{index .RepoDigests 0}}' "$TARGET_IMAGE_NAME_WITH_TAG" | cut -d '@' -f2
}
function getTagsByDigest () {
TARGET_IMAGE_NAME="$1"
TARGET_DIGEST="$2"
# prepend the image name with "library/" if it doesn't contain a slash
if [[ $TARGET_IMAGE_NAME != *"/"* ]]; then
TARGET_IMAGE_NAME="library/$TARGET_IMAGE_NAME"
fi
# get authorization token for the given image name
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$TARGET_IMAGE_NAME:pull" | jq -r .token)
# find all tags for the given image name
ALL_TAGS=$(curl -s -H "Authorization: Bearer $TOKEN" https://index.docker.io/v2/$TARGET_IMAGE_NAME/tags/list | jq -r .tags[])
# itate over all these tags
for TAG in ${ALL_TAGS[@]}; do
# get image digest
DIGEST=$(curl -s -D - -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" https://index.docker.io/v2/$TARGET_IMAGE_NAME/manifests/$TAG | grep Docker-Content-Digest | cut -d ' ' -f 2)
# if the tag matches the given digest
if [[ $TARGET_DIGEST = $DIGEST ]]; then
# "return" the tag
echo "$TAG"
fi
done
}
function getContainerImageNames () {
docker inspect $(docker ps | awk '{print $2}' | grep -v ID) | jq .[].RepoTags | grep -v "\[" | grep -v "\]" | grep " " | cut -d '"' -f2 | cut -d '/' -f2-
}
# get all image names of all local containers
IMGS_WITH_TAG=$(getContainerImageNames)
# iterate of those image names
for IMAGE_NAME_WITH_TAG in ${IMGS_WITH_TAG[@]}; do
# get the digest of the current iteration's IMAGE_NAME_WITH_TAG
DIGEST=$(getDigestByImageNameWithTag $IMAGE_NAME_WITH_TAG)
echo "TARGET_DIGEST: $DIGEST"
# get the raw image name without the tag
IMAGE_NAME=$(echo "$IMAGE_NAME_WITH_TAG" | cut -d ':' -f1)
# find all tags for this image that have the same digest
MATCHING_TAGS=$(getTagsByDigest $IMAGE_NAME $DIGEST)
echo "Image: $IMAGE_NAME_WITH_TAG"
echo "Image digest: $IMAGE_NAME"
echo "Image tags with same digest: "
echo "$MATCHING_TAGS"
echo "-----------------------------"
done
残念ながら、完了するまでに時間がかかるようです。何か悪いことをしているかどうかはわかりませんが、それが思いついた最高のことです。
これを適切に機能させる方法についてのアイデアはありますか?
Docker psはコンテナーが作成されたdocker imageタグフォームを既に印刷しているので、これはコンテナーを検査しないより良いアプローチだと思います。
docker inspect $(docker ps | awk '{print $2}' | grep -v ID) | jq .[].RepoTags
したがって、最初に実行中のコンテナーのリストを取得し、次にコンテナーを実行してjq
を使用して各イメージを検査し、そのイメージのすべてのrepoタグを取得します。
これが出力です。
更新:
ここではskopeoを使用しますが、APIを使用して実行できますが、作業は実行されます。
skopeo
をインストールする必要はありません。コンテナを実行してから、または結果を取得したら削除するか、インストール、スクリプトサポートの両方を実行できます。
running_container=$(docker ps | awk '{print $2}' | grep -v ID)
echo "running container: $running_container"
for image in $running_container
do
local_tag=$(echo "$image" | awk -F":" '{print $2}')
if [ -z $local_tag ]; then
# if tag is empty then tag is latest
local_tag="latest"
image="$image":"$local_tag"
fi
local_digest=$(docker inspect $image | jq '.[].RepoDigests[]' | awk -F"@" '{print $2}' | tr -d '"')
echo "Local digest is:" $local_digest
remote_digest=$(docker run --rm --env image=$image alexeiled/skopeo:latest ash -c "skopeo inspect docker://docker.io/$image" | jq '.Digest' | tr -d '"' )
echo $remote_digest
# option2 install the skopeo on your local system
# remote_digest=$(skopeo inspect docker://docker.io/$image | jq '.Digest' | tr -d '"')
echo "Remote digest is : "$remote_digest
if [ "${local_digest}" == "${remote_digest}" ]; then
echo "local image is up to date with remote"
else
echo "Remote image is updated; please run docker pull $image"
fi
done
レジストリから画像をプルした場合、画像検査のRepoDigestフィールドにはsha256参照が含まれます。
docker ps --format '{{.Image}}' | xargs \
docker image inspect --format '{{if .RepoDigests}}{{index .RepoDigests 0}}{{end}}'
ホスト上のnode:latest
のような単一の画像の場合、次のようになります。
docker image inspect --format '{{index .RepoDigests 0}}' node:latest
そのダイジェストは、同じタグ名のレジストリへのプッシュでは変更できません。レジストリから更新されたタグをプルすると、このダイジェスト更新が表示されます。
DockerイメージとコンテナーはIDで識別され、実行中のコンテナーの場合はそのイメージのIDを取得して、指定されたIDに対応するイメージをプルできます。
最初に、実行中のすべてのコンテナでdocker inspect
を使用して、sha256
Idがコンテナのベースとなっているイメージを取得する必要があります。
docker inspect
は、"Image"
の下の画像IDを返します。
{
"Id": "6de053a2afa4499471c5e5c2afe0b0d83c9c7e50fc7e687fb63a7ebfd2bff320",
...
},
"Image": "sha256:26eb6780e26887a6838684a549562c0404fd85c55f71e0af6c79a4da5505d2a7",
....
}
次に、それらの画像をダイジェスト(不変の識別子)でプルするだけです
$ docker pull node@sha256:the-image-digest-here
または
$ docker pull node@sha256:26eb6780e26887a6838684a549562c0404fd85c55f71e0af6c79a4da5505d2a7
運が良ければ、これらのダイジェストに対応する画像は引き続きDockerハブで利用できます。
その後、まだlatest
画像に直面していますか?これらの画像の名前を適切な名前とタグに変更し、直接使用できるように独自のDockerハブリポジトリにプルすることをお勧めします...
これにはdocker inspectコマンドを使用できます。あなたはここで答えを見ることができます https://stackoverflow.com/a/54075889/8113039