#!/bin/bash # Useful to delete a docker runtime diretory. In case of btrfs storage driver, handles deletion of btrfs # subvolumes used to store image layers. Similarly, in caes of zfs storage driver, handles deletion of # zfs datasets used to store image layers. Assumes dockerd is not running. # Note: If the $target diretory is spit across multiple volumes, this operation is a no-op. # Caution: in case of 'native' zfs storage driver which uses datasets to store layers, $target is irrelevant # because datasets are not listed under directories. This script will destroy *all* legacy datasets in the # volume. For example, consider two directories on same volume: # /mnt/cache/docker # /mnt/cache/docker-backup # Each directory holds a valid docker tree structure, maybe 'docker' is current and 'docker-backup' is # a backup. User decides he no loner needs 'docker-backup' so he invokes this script. The result will be # that not only will /mnt/cache/docker-backup be deleted, but all datasets belonging to /mnt/cache/docker # will also be deleted. This is because we cannot tell which datasets belong with which docker instance. # If /mnt/cache/docker and /mnt/cache/docker-backup were themselves datasets, then we would be able to, but # this is not implemented here. dereference() { local DIR=$1 # if directory is on user share, attempt to dereference if [[ "$DIR" == /mnt/user/* ]]; then # getfattr would return blank if /mnt/user/ is a bind-mount local DISK=$(getfattr -n system.LOCATIONS --absolute-names --only-values "$DIR" 2>/dev/null) if [[ -n "$DISK" ]]; then # whitespace in $DISK would exist if $target is split across multiple volumes [[ ! "$DISK" =~ [[:space:]] ]] && DIR="${DIR/user/$DISK}" || DIR="" fi fi echo "$DIR" } rm_docker() { local target="${1%/}" # sanity check that this is a docker folder if [[ ! -d "$target/containerd" ]]; then echo "docker_rm: $target is not a docker folder" exit 1 fi # dereference folder on user share target=$(dereference "$target") if [[ -z "$target" ]]; then echo "docker_rm: $target is split across multiple volumes" exit 1 fi if [[ -d "$target/btrfs/subvolumes" ]]; then # delete btrfs subvolumes for subvol in "$target/btrfs/subvolumes/"*; do btrfs subvolume delete -cR "$subvol" done elif [[ -d "$target/zfs" ]]; then # destroy zfs 'legacy' datasets zfs list -rHo name,mountpoint "$target" 2>/dev/null | awk '$2 == "legacy" {print $1}' | while read -r dataset; do echo "docker_rm: zfs destroy -R $dataset" zfs destroy -R "$dataset" done fi # delete files and directories echo "docker_rm: rm -rf $target" rm -rf "$target" } # delete the docker image file or folder if [[ -f /boot/config/docker.cfg ]]; then rm -f /var/local/emhttp/plugins/dynamix.docker.manager/docker.json . /boot/config/docker.cfg if [[ -f $DOCKER_IMAGE_FILE ]]; then echo "Deleting $DOCKER_IMAGE_FILE ..." rm -f "$DOCKER_IMAGE_FILE" elif [[ -d $DOCKER_IMAGE_FILE ]]; then echo "Deleting $DOCKER_IMAGE_FILE ..." rm_docker "$DOCKER_IMAGE_FILE" fi fi