update docker gc script
authorSam <sam.saffron@gmail.com>
Sun, 11 Oct 2015 22:52:53 +0000 (09:52 +1100)
committerSam <sam.saffron@gmail.com>
Sun, 11 Oct 2015 22:52:53 +0000 (09:52 +1100)
scripts/docker-gc [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index cb6e815..895edd8
@@ -39,13 +39,34 @@ set -o errexit
 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
@@ -57,13 +78,13 @@ function date_parse {
   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))
@@ -97,6 +118,27 @@ function compute_exclude_ids() {
         | 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
@@ -113,9 +155,12 @@ $DOCKER ps -a -q --no-trunc | sort | uniq > containers.all
 # 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
 
@@ -129,7 +174,9 @@ do
         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
@@ -144,7 +191,18 @@ sort | uniq > images.used
 
 # 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