Skip to content

Instantly share code, notes, and snippets.

@mmrko
Forked from lalyos/save-all-images.sh
Last active January 30, 2023 10:23
Show Gist options
  • Save mmrko/78a071d0ff2062cb199a852e2469586f to your computer and use it in GitHub Desktop.
Save mmrko/78a071d0ff2062cb199a852e2469586f to your computer and use it in GitHub Desktop.
Script to (selectively) save/load multiple Docker images
#!/usr/bin/env bash
# Script to (selectively) save/load multiple Docker images to/from a directory.
# Run ./save-load-docker-images.sh for help.
set -e
directory=$PWD
filter=""
compress=0
while getopts ":f:d:z" opt ${@:2}; do
case $opt in
f)
filter=$OPTARG
;;
d)
directory=$OPTARG
;;
z)
compress=1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
;;
esac
done
help () {
echo
echo "\
Usage: save [-f filter] [-d dir] Save all Docker images to a directory
load [-f filter] [-d dir] Find all saved images (.tar) in a directory then import to Docker
-d dir Directory to save/load images to/from (defaults to \$PWD)
-f filter Filter images by their name (inclusive)
-z Use gzip to compress/uncompress archives (saved/loaded as *.tar.gz)"
echo
}
get-image-field() {
local imageId=$1
local field=$2
: ${imageId:? required}
: ${field:? required}
docker images --no-trunc | sed -n "/${imageId}/s/ */ /gp" | cut -d " " -f $field
}
get-image-name() {
get-image-field $1 1
}
get-image-tag() {
get-image-field $1 2
}
save-all-images() {
local ids=$(docker images --no-trunc -q)
local name safename tag
for id in $ids; do
name=$(get-image-name $id)
tag=$(get-image-tag $id)
# Apply filter (if any)
if [[ ! -z "$filter" ]] && [[ ! "$name:$tag" =~ "$filter" ]];then
continue
fi
# Ignore stale images (tag == <none>)
if [[ "$tag" = "<none>" ]]; then
continue
fi
if [[ $name =~ / ]]; then
dir=${name%/*}
mkdir -p "$directory/$dir"
fi
echo "Saving $name:$tag ..."
if [[ $compress -eq 0 ]]; then
docker save -o "$directory/$name.$tag.tar" $name:$tag
else
docker save $name:$tag | gzip > "$directory/$name.$tag.tar.gz"
fi
done
}
load-all-images() {
local name safename noextension tag
if [[ $compress -eq 0 ]]; then
file_extension="tar"
else
file_extension="tar.gz"
fi
for image in $(find "$directory" -name \*.$file_extension); do
if [[ ! -z "$filter" ]] && [[ ! "$image" =~ "$filter" ]];then
continue
fi
echo "Loading $image ..."
docker load -i $image
done
}
case $1 in
save)
save-all-images
;;
load)
load-all-images
;;
*)
help
;;
esac
exit 0
@YannRobert
Copy link

@mmrko
Copy link
Author

mmrko commented May 10, 2017

Thanks a bunch 😀 added.

@aaronjpitty
Copy link

Great script thanks! :)

Worthwhile adding the following bit of information incase you come direct to this page

  • Point the Docker daemon to your Docker Machine: eval "$(docker-machine env your-docker-machine-name-goes-here)"
  • Grab the images from your Docker Machine (by running the script referred to above): ./save-load-images.sh save ./my-images
  • Unset the DOCKER env variables (which were set by the eval in step 1.)
    • unset DOCKER_TLS_VERIFY
    • unset DOCKER_CERT_PATH
    • unset DOCKER_MACHINE_NAME
    • unset DOCKER_HOST
  • Load the images into Docker for Mac: ./save-load-images.sh load ./my-images

@clijeron
Copy link

Thanks ! Working perfectly on my end.

@vijay-v6
Copy link

the script has helped me save a lot of time... thanks for that... but is there a way to modify the script to save & retag all docker images under one tar file instead of having it create & save tars in different directories?

@raajsekhar
Copy link

Very handy script >> Thanks a lot

@fedulovivan
Copy link

Many thanks for the script. Please consider "merging" fix for the load command from my fork.

There is a minor problem with handling filter option in load command.
Example: we have two tar.gz files at path /home/username/oamgui_images:

  • oamgui_container.tar.gz
  • some_other.tar.gz

Calling script as ./save-load-docker-images.sh load -z -f "oamgui_" -d /home/username/oamgui_images will try to load both files, since fullpath contains substring oamgui_. While expected behaviour is to load oamgui_container.tar.gz only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment