Skip to content

Instantly share code, notes, and snippets.

@andyneff
Last active May 3, 2017 16:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andyneff/2f4ec809199b47aa9331 to your computer and use it in GitHub Desktop.
Save andyneff/2f4ec809199b47aa9331 to your computer and use it in GitHub Desktop.
With the lack of a docker clean command, I've created a few bash functions/scripts to helps me deal with cleaning up dockers

Since docker isn't like git in that creating a docker-clean in the path will create a docker clean command, I've settled for dc_blah :(

Most of these command do NOT have safe guards yet, bad inputs can cause you to lose all your docker images. USE AT OWN RISK!

  • dc_ps - Removes all dead containers. This is safe AS LONG as you don't want to try and commit any of your dead dockers
  • dc_images - Removes all dangling images. When rebuilding a dockerfile, previous intermediate images get left behind (as dangling) this removes them
  • dc_trace - List all the image snapshots that make up a particular image. It lists the parent, grandparent, etc... all the way to the begining image. It also lists the actual size of each of these snapshots in human readable sizes
  • dc_trace_cmd - Same as dc_trace, except it also lists the "dockerfile command" that created that image. This only makes sense for images made with docker build. It makes less sense with images build by docker commit
  • dc_trace_q - Version of dc_trace displaying just the SHAs.
  • dc_images_parent_id - Not intended to be used directly, used by other functions. But this creates a list of all images and thier parents. If a line only has one sha and starts with a space, that means it has no parent. As far as I know these are images created by docker import or just the original blank image.
  • dc_children - The oppisite of dc_trace. While dc_trace show the parents, dc_children should the children, and grandchildren, etc... Since there is potential for multiple children, all of them are lists in a tree structure, indented with - to show how many generations down each image is.
  • dc_children_q - Version of dc_children diplaying just the SHAs. Pipe through tac and useful for removing all the children in order. See dc_rmi
  • dc_rmi - Removes an image and all its children. Will probably fail if containers are left behind using any of the images.
  • dc_image_list - List all the image SHAs in cache
  • dc_pid - Take a system pid number and determine which docker it is in. Blank for not in a docker.
  • dc_find_volume - List all containers (running and not-running) that are bound to a particular volume (from docker volume ls). This is useful for trying to remove a volume, but a stray container has it mounted
function dc_trace_q() {
  local parent=`docker inspect -f '{{ .Parent }}' $1` 2>/dev/null
  if [ "${parent}" != "" ]; then
    echo $parent
    dc_trace_q $parent $level
  fi
}

function dc_trace() {
  local parent=`docker inspect -f '{{ .Parent }}' $1` 2>/dev/null
  declare -i level=$2
  level=level+1
  if [ "$2" == "" ]; then
    echo 0: $1 $(numfmt --to=iec-i --suffix=B $(docker inspect -f '{{ .Size }}' $1))
  fi
  if [ "${parent}" != "" ]; then
    echo ${level}: $parent $(numfmt --to=iec-i --suffix=B $(docker inspect -f '{{ .Size }}' $parent))
    dc_trace $parent $level
  fi
}

function dc_trace_cmd() {
  local parent=`docker inspect -f '{{ .Parent }}' $1` 2>/dev/null
  declare -i level=$2
  echo ${level}: `docker inspect -f '{{ .ContainerConfig.Cmd }}' $1 2>/dev/null`
  level=level+1
  if [ "${parent}" != "" ]; then
    echo ${level}: $parent 
    dc_trace_cmd $parent $level
  fi
}

function dc_images_parent_id(){
  for d in `docker images -a -q | uniq`; do
    docker inspect -f '{{.Parent}} {{.Id}}' $d
  done
}

function dc_children(){
  dc_children_q $1 " "
}

function dc_children_q(){
  if [ "$2" != "" ]; then
    local depth=-$2
  fi
  local cache=$3
  if [ "$cache" == "" ]; then
    local cache_use=`mktemp`
    dc_images_parent_id > "${cache_use}"
    local dockid=$(docker inspect -f '{{.Id}}' $1)
  else
    local cache_use="${cache}"
    local dockid=$1
  fi

  if (( ${#dockid} < 64 )); then return; fi
  
  while read line; do
    local newid=`echo $line | awk '{print $2}'`
    echo ${depth}${newid}
    dc_children_q "${newid}" "${depth}" "${cache_use}"
  done < <(grep "^${dockid}" "${cache_use}")

  if [ "${cache}" == "" ]; then
    \rm "${cache_use}"
  fi
}

function dc_rmi(){
  docker rmi $(dc_children_q $1 | tac)
  docker rmi $1
}

function dc_pid(){
  local ds=($(docker ps --format '{{.ID}}' | xargs docker inspect -f '{{.State.Pid}} {{.Id}}'))
  local ppid=$1
  while (( ${ppid} != 1 )); do 
    for x in $(seq 0 2 ${#ds[@]}); do
      if [ "${ds[$x]}" == "${ppid}" ]; then
        echo ${ds[$(($x+1))]}
        return
      fi
    done
    ppid=$(ps -ho ppid $ppid)
  done
}

function dc_find_volume()
{
  local volumes=($(docker inspect --format '{{$x:=.Name}} {{range .Mounts}} {{if .Name}} {{$x}}@{{ .Name }} {{end}} {{end}}' $(docker ps -aq)))
  local x
  for x in "${volumes[@]}"; do
    if [[ ${x} =~ .*@$1 ]]; then
      echo ${x%@*}
    fi
  done
}

alias dc_ps='docker rm $(docker ps --filter=status=exited --filter=status=created -q)'
alias dc_images='docker rmi $(docker images -a --filter=dangling=true -q)'
alias dc_images_list='docker images -a -q | uniq'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment