I am trying to stop / prune docker containers according to 2 conditions:
- image name
- time they've been running for
For instance, I could want to stop all containers from image image-name that have been running for over 24h.
By reading the documentation, it seems the --filter
option is not consistent at all since docker container prune
has the until
filter, which is useful to filter containers by age but doesn't have the ancestor
filter. This filter is available for docker ps
though, and it filters by image name. If I could run docker ps
with until
, I could just pipe the ids to docker stop
but again, the filters are not consistent between commands.
Finally, docker container prune
has a label
filter but I can't seem to find what a label is in docker or if it could be useful in this case. I tried label=image=<image-name>
without success.
Update: I've realized docker container prune
does not have a way of removing running containers, only stopped ones, so I'd need to find a way to fitler by age on docker ps
CodePudding user response:
As I said in comment it is not possible to handle removing with only docker command, but it is possible handle it with one line bash command:
docker rm -f $(docker ps -a --format "{{.ID}}|{{.Image}}|{{.CreatedAt}}" | grep "imagename" | grep -v "$(date %Y-%m-%d)" | awk -F'|' '{print$1}' | xargs)
grep "imagename"
→ filter lines withimagename
onlygrep -v "$(date %Y-%m-%d)"
→ get only containers that created not today (It can't be tomorrow by design so only yesterday or earlier cases are possible)awk -F'|' '{print$1}'
→ get only container ID and remove unnecessary information (image ID, date)xargs
will replace new lines with whitespacesdocker rm -f
will remove IDs provided with$(docker ps ...)
comamnd
But this command is little bit different than you want. It will remove all yesterday's containers even if it created 1 minute ago (if container created at 23:59 and you run this command at 00:00)
So you may add one another grep
: | grep -v $(date "%Y-%m-%d" --date="1 days ago")
. That will allow to keep containers running less than ~48 hours
Update: handle removing with hour level
docker rm -f $(docker ps -a --format "{{.ID}}|{{.Image}}|{{.CreatedAt}}" | grep "imagename" | egrep -v "$(printf "$(for i in {1..24}; do echo $i' hour ago'; done)" | date '%Y-%m-%d %H' -f - | sed -z 's/\n/|/g' | sed 's/.$//')" | awk -F'|' '{print$1}' | xargs)
command remove all containers that created not in previous 24 hours from now
*tested at Ubuntu. This command may not work in Unix-based systems (include MacOS) because different sed
syntax
CodePudding user response:
So, it'd be nice to be able to do this only using docker commands but for now I found a way using bash and awk:
containers=$(docker ps -a --format "{{.ID}}###{{.Image}}###{{.CreatedAt}}" | grep "imagename")
date_limit="2022-05-19"
while IFS= read -r line; do
id="$(echo $line | awk '{split($0,a,"###"); print a[1]}')"
image="$(echo $line | awk '{split($0,a,"###"); print a[2]}')"
date="$(echo $line | awk '{split($0,a,"###"); print a[3]}')"
echo "Container $id with date $date and image $image"
echo $line | if [[ "$date" > "$date_limit" ]];
then echo "removing"; docker rm -f $id;
else echo "not removing";
fi
done <<< "$containers"
This prints the containers' ids, image name and date. Parses each line and compares the date with a threshold (date_limit) and compares the image name with the desired name. If the desired conditions are met, it removes the container (with -f flag, which kills the container if it's still running)