Delete docker images with same name - docker

Server storing multiple docker images with same name but with different tags, I am finding the good command which will search docker images with same name, but with different tags, and delete all, saving only the newest.
Example.
TestImage:v1
TestImage:v2
TestImage:v3
TestImage:v4
The command will delete all images which have name "TestImage" but save TestImage:v4 (which is newest by date).
The actual command .

Provided you have the docker cli installed, the following should work:
image_ids=$(docker image ls "$name" -q | tail -n +2 | xargs)
docker image rm "$image_ids"
The first command loads all local images with the given name. Using the -q flag means that only the image ids are being outputted.
the tail program then skips the first one of these ids (in other words, starts reading at line 2). Since images are sorted from new to old, this means the newest image is skipped.
The xargs then brings all the outputted ids into the same line, so that docker can interpret them easily.
The ids obtained in that step may look something like this:
ae3c4906b72c 650d66a00131 18cac929dc4f
docker image rm will then remove all images with these ids.

Related

How to delete a docker image based on a pattern and timestamp together

I have been trying to delete the docker images based on a pattern and a given timestamp, using grep command to search for a pattern and including filter command with until, so that I'd get the docker images deleted based on the given requirements. For a reference the command I used:
docker images -a | grep "<pattern>" | xargs docker rmi -f
Above command is working but I want to delete a docker images based on some pattern as above but I need to include a timestamp into it to be more specific, using this filter command:
--filter"until<timestamp>"

How do I see extra tags on a local Docker image?

When I build a Docker image locally with a tag, then assign a secondary tag, I am unable to list all of the tags for that image.
I'm losing tags either on the build, save or load of docker images and I'm trying to track the state of my image at every step. Please note that this is a local Docker file (as in on my laptop), and can't be sent to a remote repository. When I run docker images I can see the image created with one of the tags, but not all of them.
$ docker build -t my/repo:first_tag
$ docker tag my/repo:first_tag my/repo:second_tag
When I run docker images I only see the first tag shown as the tag.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my/repo first_tag abcd1234 6 seconds ago 100MB
I would like to have some way of showing that image with all of the tags, something like:
my/repo:
first_tag
second_tag
Does a command like this exist and, if so, what is it?
EDIT: It turns out I was adding tags wrong and the code show above wasn't representative of it. What I was doing was actually:
$ docker build -t my/repo:first_tag
$ docker tag my/repo:first_tag my/repo
Note that the second tag doesn't have an actual tag on it. When I actually run the code in the question I get the following output:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my/repo second_tag abcd1234 6 seconds ago 100MB
my/repo first_tag abcd1234 6 seconds ago 100MB
If you want to list tags for a particular image, you can run :
docker images my/repo --format="{{ .Tag }}"
--format is used here to only keep interesting columns. By default, docker images my/repo will return all info about my/repo (repository, tag, image id, created and size), like docker images (without filtering repository) does.
Edit : group images by tags
Since --format option placeholders are limited (https://docs.docker.com/engine/reference/commandline/images/#format-the-output), you cannot access some interesting properties as .RepoTags to retrieve all tags associated with an image digest. However, you could do this by docker inspecting desired images and using some shell and jq magic (jq is a tool to manipulate JSON) :
docker images my/repo --format="{{ .ID }}" | \
sort | uniq | \
xargs docker inspect | \
jq -r '.[] | [ .Id, (.RepoTags | join(",")) ] | #csv'
Explanations :
first, retrieve all images IDs (--format="{{ .ID }}") related to my/repo
remove duplicates (sort | uniq) if any (because of multiple tags per image ID)
for each image (xargs), inspect that image (docker inspect) :
use jq to retrieve a string like <id of the image>,<tags related to the image>. Tags related to this image are separated by a comma (join(","))
Example result :
"sha256:abcd1234...","my/repo:v1"
"sha256:abcd2345...","my/repo:v2"
"sha256:abcd3456...","my/repo:v3,my/repo:tag"
Get RepoTags by example:
docker image inspect my/backend:latest-qa | jq -r '.[] | (.RepoTags)'
ouput:
[
"my/backend:0.12.3-qa",
"my/backend:latest-qa"
]

Docker image name is changed automatically

I've running several containers on my host (Ubuntu Server)
I ran docker container via a command, like below
sudo docker run -d -p 5050:80 gitname/reponame
And after I call sudo docker ps and it shows
CONTAINER ID: e404ffa2bc6b
IMAGE: gitname/reponame
COMMAND: "dotnet run --server…"
CREATED: 14 seconds ago
STATUS: Up 12 seconds
PORTS: 5050/tcp, 0.0.0.0:5050->80/tcp
NAMES: reverent_mcnulty
And in a week I run sudo docker ps again and it shows another info where IMAGE was changed and it looks like ba2486f19dc0
I don't understand why.
It's problem for me because for stopping containers I use the command:
sudo docker stop $(sudo docker ps | awk '{ print $1,$2 }' | grep gitname/reponame | awk '{print $1 }')
And it doesn't work because image name already was changed
Every Docker image has a unique hex ID. These IDs will be different on different systems (even docker pull of the same image), but every image has exactly one ID.
Each image has some number of tags associated with it. This could be none, or multiple. docker tag will add a tag to an existing image; docker rmi will remove a tag, and also (if there are no other tags on the image, no other images using the image as a base, and no extant containers using the image) remove the image.
It's possible to "steal" the tag from an existing image. The most obvious way to do this is with docker build:
cat >Dockerfile <<EOF
FROM busybox
COPY file.txt /
EOF
echo foo > file.txt
docker build -t foo .
docker images
# note the ID for foo:latest
echo bar > file.txt
docker build -t foo .
docker images
# note the old ID will show as foo:<none>
# note a different ID for foo:latest
An explicit docker tag can do this too. Images on Docker Hub and other repositories can change too (ubuntu:16.04 is routinely re-published with security updates), and so if you docker pull an image you already have it can cause the old image to "lose its name" in favor of a newer version of that image.
How does this interact with docker run and docker ps? docker run can remember the image tag an image was started with, but if the image no longer has that tag, it forgets that datum. That's why your docker ps output reverts to showing the hex ID of the image.
There are a couple of ways around this for your application:
If the image is one you're building yourself, always use an explicit version tag (could just be the current datestamp) both when building and running the image. Then you'll never overwrite an existing image's tag. ("Don't use :latest tags.")
Use docker run --name to keep track of which container is which, and filter based on that, not the image tag. (#quentino's suggestion from comments.)
Don't explicitly docker pull in your workflow. If you don't have an image, docker run will automatically pull it for you. This will avoid existing images getting minor updates and also will avoid existing images losing their names.

Remove older docker images but not layers that are still referenced

Say I have a build machine which builds many docker images myimage:myversion. I consume about 1GB disk space per 100 images created and I certainly don't need all of them. I'd like to keep, say, the most recent 10 images (and delete everything older) but I want to make sure I have all of the cached layers from the 10 builds/image. If I have all of the layers cached, then I'm more likely to have a fast build on my next run.
The problem is all of the images (very old and brand new) share a lot of layers so I can't blindly delete the old ones as there is a ton of overlap with the new ones.
I don't want to use docker image prune (https://docs.docker.com/config/pruning/#prune-images) as that depends on which containers I have (regardless of state) and am deleting the containers so prune will end up deleting way too much stuff.
Is there a simple command I can run periodically to achieve the state I described above?
Simple, no, but some shell wizardry is possible. I think this shell script will do what you want:
#!/bin/sh
docker images --filter 'reference=myimage:*' \
--format '{{ .CreatedAt }}/{{ .ID }}/{{ .Repository }}:{{ .Tag }}' \
| sort -r \
| tail +11 \
| cut -d / -f 2 \
| xargs docker rmi
(You might try running this one step at a time to see what comes out.)
In smaller pieces:
List all of the myimage:* images in a format that starts with their date. (If you're using a private registry you must include the registry name as a separate part and you must explicitly include the tag; for instance to list all of your GCR images you need -f 'reference=gcr.io/*/*:*'.)
Sort them, by the date, newest first.
Skip the first 10 lines and start printing at the 11th.
Take only the second slash-separated field (which from the --format option is the hex image ID).
Convert that to command-line arguments to docker rmi.
The extended docker images documentation lists all of the valid --format options.

Docker - remove all but last N images

I am trying to build a small script that removes all docker images besides a small "cache" of N last images (for rolling back to one of the last working versions).
Is there an idiomatic way to do this?
You can use the tail command to accomplish this.
Let's say you only want to keep the most recent 5 images. You can tell tail to show you the list starting with the nth line. For 5 images, you would want tail to start on the 6th line:
tail -n +6
Pair this with docker to show a list of your image IDs, which are sorted by most recent, by default.
docker images -q | tail -n +6
You can pass all of that to the remove images command. This assumes you're using the bash shell; if you use a csh-derived shell, you may need different syntax.
docker rmi $(docker images -q | tail -n +6)

Resources