-
-
Save mmrko/78a071d0ff2062cb199a852e2469586f to your computer and use it in GitHub Desktop.
#!/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 |
Thanks a bunch 😀 added.
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
Thanks ! Working perfectly on my end.
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?
Very handy script >> Thanks a lot
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.
hi, I added support for gzip if you're interested :
https://gist.github.com/YannRobert/3824d0079a1da84173850339334ba24e/d29b79f775fd7ad2cb157fe63e8b1d1e1de2a55d