Home > Back-end >  Docker filter containers both by image name and age
Docker filter containers both by image name and age

Time:05-21

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 with imagename only
  • grep -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 whitespaces
  • docker 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)

  • Related