Skip to content

Delete Old Docker Containers Automatically

Updated: at 05:59 AM

Docker offers great convenience for running scripts regularly, especially when compared to the traditional method of running scripts that may have compatibility issues across different servers and versions. However, a challenge that arises is the difficulty of retrieving and terminating scripts that are timing out for unknown reasons.

This is where this convenient script comes into play:

#!/bin/bash

# Validate arguments
if [ "$#" -ne 2 ]; then
    echo "Usage: $0 <hours> <image_name>"
    exit 1
fi

HOURS="$1"
IMAGE="$2"
CURRENT_TIME=$(date +%s)

# List only running containers using the specified image and get their IDs and creation times
docker ps --filter "ancestor=$IMAGE" --filter "status=running" --format '{{.CreatedAt}}\t{{.ID}}' | while IFS=$'\t' read -r CREATED_AT CONTAINER_ID; do
    # Normalize creation time to be compatible with date command across different environments
    # Assuming Docker returns creation time in a format like: 2024-02-20 15:20:01 +0100 CET
    # We need to adjust it to a more standard format for the date command
    NORMALIZED_CREATED_AT=$(echo "$CREATED_AT" | sed -E 's/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}).*/\1/')

    # Convert creation time to timestamp
    CREATED_AT_TIMESTAMP=$(date -d "$NORMALIZED_CREATED_AT" +%s 2>/dev/null)
    if [ $? -ne 0 ]; then
        echo "Error parsing date for container $CONTAINER_ID. Skipping..."
        continue
    fi

    # Calculate the age of the container in hours
    AGE=$(( (CURRENT_TIME - CREATED_AT_TIMESTAMP) / 3600 ))

    if [ "$AGE" -ge "$HOURS" ]; then
        echo "Stopping container $CONTAINER_ID (Age: $AGE hours)"
        docker stop "$CONTAINER_ID"
    fi
done

Save this script in a convenient directory so you can run it manually or set it to run regularly using a cronjob.

The script requires two arguments:

./stop_old_containers.sh <hours> <image_name>