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>
- The term
hours
refers to the minimum number of hours required for a container to be considered as timing out. - To avoid inadvertently killing off all long-lasting Docker containers on your server, specify the
image_name
when targeting containers for removal.