GRACE_PERIOD_SECONDS=${GRACE_PERIOD_SECONDS:=3600}
STATE_DIR=${STATE_DIR:=/var/lib/docker-gc}
DOCKER=${DOCKER:=docker}
+PID_DIR=${PID_DIR:=/var/run}
+
+for pid in $(pidof -s docker-gc); do
+ if [[ $pid != $$ ]]; then
+ echo "[$(date)] : docker-gc : Process is already running with PID $pid"
+ exit 1
+ fi
+done
+
+trap "rm -f -- '$PID_DIR/dockergc'" EXIT
+
+echo $$ > $PID_DIR/dockergc
+
+
EXCLUDE_FROM_GC=${EXCLUDE_FROM_GC:=/etc/docker-gc-exclude}
if [ ! -f "$EXCLUDE_FROM_GC" ]
then
EXCLUDE_FROM_GC=/dev/null
fi
+EXCLUDE_CONTAINERS_FROM_GC=${EXCLUDE_CONTAINERS_FROM_GC:=/etc/docker-gc-exclude-containers}
+if [ ! -f "$EXCLUDE_CONTAINERS_FROM_GC" ]
+then
+ EXCLUDE_CONTAINERS_FROM_GC=/dev/null
+fi
+
EXCLUDE_IDS_FILE="exclude_ids"
+EXCLUDE_CONTAINER_IDS_FILE="exclude_container_ids"
function date_parse {
if date --utc >/dev/null 2>&1; then
fi
}
-
# Elapsed time since a docker timestamp, in seconds
function elapsed_time() {
# Docker 1.5.0 datetime format is 2015-07-03T02:39:00.390284991
# Docker 1.7.0 datetime format is 2015-07-03 02:39:00.390284991 +0000 UTC
utcnow=$(date -u "+%s")
- without_ms="${1:0:19}"
+ replace_q="${1#\"}"
+ without_ms="${replace_q:0:19}"
replace_t="${without_ms/T/ }"
epoch=$(date_parse "${replace_t}")
echo $(($utcnow - $epoch))
| sed 's/^/^/' > $EXCLUDE_IDS_FILE
}
+function compute_exclude_container_ids() {
+ # Find containers matching to patterns listed in EXCLUDE_CONTAINERS_FROM_GC file
+ # Implode their values with a \| separator on a single line
+ PROCESSED_EXCLUDES=`cat $EXCLUDE_CONTAINERS_FROM_GC \
+ | xargs \
+ | sed -e 's/ /\|/g'`
+ # The empty string would match everything
+ if [ "$PROCESSED_EXCLUDES" = "" ]; then
+ touch $EXCLUDE_CONTAINER_IDS_FILE
+ return
+ fi
+ # Find all docker images
+ # Filter out with matching names
+ # and put them to $EXCLUDE_CONTAINER_IDS_FILE
+ $DOCKER ps -a \
+ | grep -E "$PROCESSED_EXCLUDES" \
+ | awk '{ print $1 }' \
+ | tr -s " " "\012" \
+ | sort -u > $EXCLUDE_CONTAINER_IDS_FILE
+}
+
# Change into the state directory (and create it if it doesn't exist)
if [ ! -d "$STATE_DIR" ]
then
# List running containers
$DOCKER ps -q --no-trunc | sort | uniq > containers.running
-# compute ids of containers to exclude from GC
+# compute ids of container images to exclude from GC
compute_exclude_ids
+# compute ids of containers to exclude from GC
+compute_exclude_container_ids
+
# List containers that are not running
comm -23 containers.all containers.running > containers.exited
echo $line >> containers.reap.tmp
fi
done
-cat containers.reap.tmp | sort | uniq > containers.reap
+
+# List containers that we will remove and exclude ids.
+cat containers.reap.tmp | sort | uniq | grep -v -f $EXCLUDE_CONTAINER_IDS_FILE > containers.reap || true
# List containers that we will keep.
comm -23 containers.all containers.reap > containers.keep
# List images to reap; images that existed last run and are not in use.
$DOCKER images -q --no-trunc | sort | uniq > images.all
-comm -23 images.all images.used | grep -v -f $EXCLUDE_IDS_FILE > images.reap || true
+
+# Find images that are created at least GRACE_PERIOD_SECONDS ago
+echo -n "" > images.reap.tmp
+cat images.all | while read line
+do
+ CREATED=$(${DOCKER} inspect -f "{{.Created}}" ${line})
+ ELAPSED=$(elapsed_time $CREATED)
+ if [[ $ELAPSED -gt $GRACE_PERIOD_SECONDS ]]; then
+ echo $line >> images.reap.tmp
+ fi
+done
+comm -23 images.reap.tmp images.used | grep -v -f $EXCLUDE_IDS_FILE > images.reap || true
# Reap containers.
xargs -n 1 $DOCKER rm --volumes=true < containers.reap &>/dev/null || true