J'ai un tas de conteneurs Docker en cours d'exécution sur un serveur et j'ai utilisé la "dernière" balise ou aucune balise pour tous. Maintenant, je veux figer les versions d'images, mais je n'ai aucune idée quand j'ai tiré ces images, donc je ne peux pas dire à quelle version "la plus récente" fait référence. docker ps
me montre simplement que les conteneurs utilisent le "dernier" ou aucun tag, comme ceci:
# 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
...
Toutes les images que j'utilise sont des images publiques du hub docker.
J'ai pensé que je pourrais peut-être utiliser l'ID hexadécimal que docker ps affiche pour tous les conteneurs, mais j'ai réalisé que les ID sont des ID de conteneur et non des ID d'image.
Est-il possible d'obtenir les ID/hachages d'image de tous les conteneurs en cours d'exécution, puis de rechercher toutes les balises correspondantes ou quelque chose comme ça?
Version Docker: 18.09.1, build 4c52b90
Modifier:
Il y a donc eu des réponses montrant comment obtenir les identifiants (résumés) des images, mais je dois en quelque sorte trouver les balises réelles de ces images. Après avoir fait des recherches, j'ai constaté que le hub docker possède une API et qu'il existe un moyen d'obtenir toutes les balises pour une image donnée et qu'il existe un moyen d'obtenir le résumé pour une image + balise donnée. Après avoir regardé l'API et de nombreux exemples de stackoverflow, j'ai trouvé ceci: (Il comprend également le code requis pour obtenir le résumé des images locales, pris sous forme des réponses ci-dessous)
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
Malheureusement, cela semble prendre une éternité pour finir. Je ne sais pas si je fais quelque chose de mal, mais c'est la meilleure chose que j'ai pu trouver.
Des idées sur la façon de faire fonctionner cela correctement?
Je pense que c'est une meilleure approche sans inspecter le conteneur, car docker ps imprime déjà le formulaire de balise d'image docker dans lequel le conteneur est créé.
docker inspect $(docker ps | awk '{print $2}' | grep -v ID) | jq .[].RepoTags
Donc, tout d'abord, cela obtient la liste des conteneurs en cours d'exécution, puis inspectez chaque image utilisée en exécutant le conteneur et en utilisant jq
récupérez toutes les balises repo de cette image.
Voici la sortie.
Mise à jour:
Voici que vous allez utiliser skopeo , vous pouvez le faire en utilisant l'API mais fera l'effort, alors pourquoi si vous avez skopeo
Vous n'avez pas besoin d'installer skopeo
vous pouvez exécuter le conteneur puis ou supprimer une fois le résultat obtenu, ou vous pouvez installer, le script prend en charge les deux
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
Le champ RepoDigest dans l'inspection d'image aura une référence sha256 si vous avez extrait l'image d'un registre:
docker ps --format '{{.Image}}' | xargs \
docker image inspect --format '{{if .RepoDigests}}{{index .RepoDigests 0}}{{end}}'
Pour une seule image comme node:latest
sur votre hôte, qui ressemble à:
docker image inspect --format '{{index .RepoDigests 0}}' node:latest
Ce résumé ne peut pas être modifié par un push vers le registre du même nom de balise. Lorsque vous retirez la balise mise à jour du registre, vous verrez cette mise à jour de résumé.
Les images et les conteneurs Docker sont identifiés par un ID et pour un conteneur en cours d'exécution, vous pouvez obtenir l'ID de son image, puis extraire l'image correspondant à l'ID donné.
Vous devez d'abord utiliser docker inspect
sur tous vos conteneurs en cours d'exécution afin d'obtenir le sha256
Id l'image sur laquelle le conteneur est basé.
docker inspect
renvoie l'ID de l'image sous "Image"
:
{
"Id": "6de053a2afa4499471c5e5c2afe0b0d83c9c7e50fc7e687fb63a7ebfd2bff320",
...
},
"Image": "sha256:26eb6780e26887a6838684a549562c0404fd85c55f71e0af6c79a4da5505d2a7",
....
}
Ensuite, il vous suffit de tirer ces images par résumé (identifiant immuable)
$ docker pull node@sha256:the-image-digest-here
ou
$ docker pull node@sha256:26eb6780e26887a6838684a549562c0404fd85c55f71e0af6c79a4da5505d2a7
Si vous avez de la chance, des images correspondant à ces résumés sont toujours disponibles dans le hub docker.
Après cela, si vous êtes toujours face à des images latest
, je vous suggérerai de renommer ces images avec un nom et une balise appropriés et de les insérer dans votre propre référentiel de docker pour pouvoir les utiliser directement ...
La commande docker inspect peut être utilisée pour cela. Vous pouvez jeter un oeil à la réponse ici https://stackoverflow.com/a/54075889/8113039