Last active
March 25, 2023 19:40
-
-
Save JM1/ab8c3beea108ea14a6b8955050f36357 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# vim:set tabstop=8 shiftwidth=4 expandtab: | |
# kate: space-indent on; indent-width 4; | |
# shellcheck disable=SC2039 | |
# | |
# Copyright (c) 2016-2022 Jakob Meng, <[email protected]> | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
# NOTE: declare local variables first and initialize them later because return code of "local ..." is always 0 | |
set -e | |
#set -x | |
prg=$(basename "$0") | |
version() { | |
cat << ____EOF | |
$prg version 0.5 | |
Copyright (c) 2016-2022 Jakob Meng, <[email protected]> | |
____EOF | |
} | |
help() { | |
cat << ____EOF | |
Usage: $prg [OPTIONS] COMMAND [arg...] | |
$prg [ --help | -v | --version ] | |
A helper script for docker. | |
Options: | |
-h, --help Print usage | |
-v, --version Print version information and quit | |
Commands: | |
attach Attach to a running container | |
db_add_tag Add tag for (all) images stored in database | |
db_build Build (all) images stored in database | |
db_example Show database example | |
db_pull Pull (all) images stored in database from Docker Hub | |
db_push Push (all) images stored in database to Docker Hub | |
rm Remove one or more containers | |
rmi Remove one or more images | |
save Save one or more images to a tar archive (streamed to STDOUT by default) | |
start Start one or more stopped containers | |
stop Stop one or more running containers | |
try_attach Try to attach to a running container else run new process in a container first | |
try_exec Try to run a new process in an existing container else run and pause a container first | |
help Print usage | |
Run '$prg COMMAND --help' for more information on a command. | |
____EOF | |
} | |
stderr() { | |
local _msg | |
while read -r _msg | |
do | |
echo "$_msg" 1>&2 | |
done | |
} | |
error() { | |
stderr << ____EOF | |
ERROR: $* | |
____EOF | |
} | |
warn() { | |
stderr << ____EOF | |
WARN: $* | |
____EOF | |
} | |
attach() { | |
help() { | |
cat << ________EOF | |
Usage: $prg attach [OPTIONS] [CONTAINER] | |
Attach to a running container | |
Options: | |
--debug Print commands issued by $prg | |
-l, --latest Attach to latest created container | |
-o OPTION Pass additional options to docker | |
-h, --help Print usage | |
________EOF | |
} | |
local _latest="no" | |
local _options="" | |
local _ctnr="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg attach" requires at least 1 argument(s). | |
See '$prg attach --help'. | |
Usage: $prg attach [OPTIONS] [CONTAINER] | |
Attach to a running container | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--debug") | |
_debug="yes" | |
;; | |
"-l"|"--latest") | |
_latest="yes" | |
;; | |
"-o") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: -o" | |
return 255 | |
fi | |
_options="$_options $2" | |
shift | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
if [ -n "$_ctnr" ]; then | |
error "CONTAINER has already been set to $_ctnr." | |
return 255 | |
fi | |
_ctnr="$1" | |
;; | |
esac | |
shift | |
done | |
local _cmd="docker attach " | |
_cmd="$_cmd $_options" | |
if [ "$_latest" = "yes" ]; then | |
local _lc | |
_lc="$(docker ps -q -l)" | |
if [ "$_lc" = "" ]; then | |
error "No container found." | |
return 255 | |
fi | |
if [ "$_ctnr" != "" ]; then | |
error "CONTAINER and flag '-l' are mutual exclusive." | |
return 255 | |
fi | |
_ctnr="$_lc" | |
fi | |
if [ "$_ctnr" = "" ]; then | |
error "No container specified." | |
return 255 | |
fi | |
_cmd="$_cmd $_ctnr " | |
( | |
[ "$_debug" = "yes" ] && set -x | |
# shellcheck disable=2086 | |
eval $_cmd | |
) | |
} | |
_test_db() { | |
local _db="$1" | |
if [ -z "$_db" ]; then | |
error "No image database given." | |
return 255 | |
fi | |
if [ ! -e "$_db" ]; then | |
error "Database '$_db' does not exist." | |
return 255 | |
fi | |
if ! which jq >/dev/null 2>&1; then | |
error "'jq' not found. On Debian or its derivatives run: sudo apt-get install jq" | |
return 255 | |
fi | |
if ! jq -e . >/dev/null 2>&1 "$_db"; then | |
error "Failed to parse Database '$_db'." | |
return 255 | |
fi | |
return 0 | |
} | |
_foreach_image_in_db() { | |
local _db="$1" | |
local _included_images="$2" | |
local _f="$3" | |
shift 3 | |
local _f_args | |
_f_args=$(printf " '%s'" "$@") | |
local _db_length | |
_db_length="$(jq '.|length' "$_db")" | |
#if [ "$_db_length" -eq 0 ]; then | |
# error "Database is empty." | |
# return 255 | |
#fi | |
( | |
local _db_directory | |
_db_directory="$(dirname "$(readlink -e "$_db")")" | |
cd "$_db_directory" # allows shorter relative paths in db | |
for i in $(seq 0 $(("$_db_length"-1))); do | |
local _entry | |
_entry="$(jq ".[$i]" "$_db")" | |
local _user | |
local _name | |
local _tag | |
local _path | |
local _add | |
local _pull | |
for key in user name tag path add pull; do | |
if echo "$_entry" | jq -e "has(\"$key\")" >/dev/null; then | |
local _tmp; | |
_tmp="$(echo "$_entry" | jq --raw-output ".[\"$key\"]")" | |
eval _$key="\$_tmp" # \$_tmp is required to not eval contents of _tmp | |
else | |
eval _$key="" | |
fi | |
done | |
if [ -z "$_user" ]; then | |
error "Image tag name is missing <user> in <user>/<name>:<tag>" | |
return 255 | |
fi | |
if [ -z "$_name" ]; then | |
error "Image tag name is missing <name> in <user>/<name>:<tag>" | |
return 255 | |
fi | |
if [ -z "$_tag" ]; then | |
warn "Image tag name is missing <tag> in <user>/<name>:<tag>, falling back to tag 'latest'" | |
_tag="latest" | |
fi | |
if [ -z "$_pull" ]; then | |
_pull="false" | |
elif [ "$_pull" != "true" ] && [ "$_pull" != "false" ]; then | |
error "Key 'pull' must be 'true' or 'false'" | |
return 255 | |
fi | |
if [ -n "$_included_images" ] && ! ( | |
(echo "$_included_images" | grep -w "$_name" >/dev/null) || | |
(echo "$_included_images" | grep -w "$_user/$_name" >/dev/null) || | |
(echo "$_included_images" | grep -w "$_user/$_name:$_tag" >/dev/null) | |
); then | |
continue | |
fi | |
if [ -n "$_add" ]; then | |
# json to string list | |
local _add_length | |
_add_length="$(echo "$_add" | jq '.|length')" | |
local _tmp="" | |
for j in $(seq 0 $(("$_add_length"-1))); do | |
local _add_entry | |
_add_entry="$(echo "$_add" | jq --raw-output ".[$j]")" | |
_tmp="$_tmp '$_add_entry'" | |
done | |
_add="$_tmp" | |
fi | |
eval set -- "$_f_args" | |
$_f "$_user" "$_name" "$_tag" "$_path" "$_add" "$_pull" "$@" | |
set -- | |
done | |
) | |
} | |
db_add_tag() { | |
help() { | |
cat << ________EOF | |
Usage: $prg db_add_tag [OPTIONS] DB TAG [IMAGE...] | |
Add tag for (all) images stored in database | |
Options: | |
--source-tag TAG Override tag from database | |
--debug Print commands issued by $prg | |
-h, --help Print usage | |
________EOF | |
} | |
local _source_tag="" | |
local _db="" | |
local _target_tag="" | |
local _imgs="" | |
local _debug="" | |
if [ $# -le 1 ]; then | |
stderr << ________EOF | |
"$prg db_add_tag" requires at least 2 argument(s). | |
See '$prg db_add_tag --help'. | |
Usage: $prg db_add_tag [OPTIONS] DB TAG [IMAGE...] | |
Add tag for (all) images stored in database | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--source-tag") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: --source-tag" | |
return 255 | |
fi | |
_source_tag="$2" | |
shift | |
;; | |
"--debug") | |
_debug="yes" | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
if [ -z "$2" ]; then | |
error "missing DB arg" | |
return 255 | |
fi | |
_db="$1" | |
_target_tag="$2" | |
shift 2 | |
_imgs="$*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
add_tag() { | |
local _user="$1" | |
local _name="$2" | |
local _tag="$3" | |
local _path="$4" | |
local _add="$5" | |
local _pull="$6" | |
local _src_tag="$7" | |
local _tgt_tag="$8" | |
if [ -n "$_src_tag" ]; then | |
_tag="$_src_tag" | |
fi | |
echo "Adding $_user/$_name:$_tgt_tag to $_user/$_name:$_tag" | |
docker tag "$_user/$_name:$_tag" "$_user/$_name:$_tgt_tag" | |
} | |
_test_db "$_db" | |
_foreach_image_in_db "$_db" "$_imgs" add_tag "$_source_tag" "$_target_tag" | |
} | |
db_build() { | |
help() { | |
cat << ________EOF | |
Usage: $prg db_build [OPTIONS] DB [IMAGE...] | |
Build (all) images stored in database | |
Options: | |
--tag TAG Override tag from database | |
--force Do not use cache and pull newer version of the image | |
--debug Print commands issued by $prg | |
-h, --help Print usage | |
________EOF | |
} | |
local _tag="" | |
local _force="" | |
local _db="" | |
local _imgs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg db_build" requires at least 1 argument(s). | |
See '$prg db_build --help'. | |
Usage: $prg db_build [OPTIONS] DB [IMAGE...] | |
Build (all) images stored in database | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--tag") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: --tag" | |
return 255 | |
fi | |
_tag="$2" | |
shift | |
;; | |
"--force") | |
_force="yes" | |
;; | |
"--debug") | |
_debug="yes" | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_db="$1" | |
shift | |
_imgs="$*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
build_image() { | |
local _user="$1" | |
local _name="$2" | |
local _tag="$3" | |
local _path="$4" | |
local _add="$5" | |
local _pull="$6" | |
local _override_tag="$7" | |
local _force="$8" | |
if [ -n "$_override_tag" ]; then | |
_tag="$_override_tag" | |
fi | |
[ -n "$_pull" ] || return 255 # assert | |
local _no_cache=false | |
if [ "$_force" = "yes" ]; then | |
_pull=true | |
_no_cache=true | |
fi | |
local _fail=no | |
local _tmpdir="" | |
if [ -n "$_add" ]; then | |
_tmpdir="$(mktemp --tmpdir --directory "docker_build_img_$(date +%Y%m%d%H%M%S).XXXXXX")" | |
fi | |
set +e # workaround for https://stackoverflow.com/a/19789651/6490710 | |
( | |
set -e | |
if [ -n "$_add" ]; then | |
eval set -- "$_add" | |
for req in \ | |
"$_path"/* \ | |
"$_path"/.[^.]* \ | |
"$@" \ | |
; do | |
cp -ran "$req" "$_tmpdir/" | |
done | |
set -- | |
cd "$_tmpdir" | |
else | |
cd "$_path" | |
fi | |
echo "Building $_user/$_name:$_tag in $PWD" | |
docker build --pull=$_pull --no-cache=$_no_cache -t "$_user/$_name:$_tag" . | |
) | |
local errc=$? | |
set -e | |
[ $errc -ne 0 ] && _fail=yes | |
# first remove temporary dir and ... | |
if [ -n "$_tmpdir" ] && [ -d "$_tmpdir" ]; then | |
command rm -r "$_tmpdir" # command rm and not function rm | |
fi | |
# ... then return on error | |
if [ "$_fail" = "yes" ]; then | |
return 255 | |
fi | |
} | |
_test_db "$_db" | |
_foreach_image_in_db "$_db" "$_imgs" build_image "$_tag" "$_force" | |
} | |
db_example() { | |
help() { | |
cat << ________EOF | |
Usage: $prg db_example [OPTIONS] | |
Show database example | |
Options: | |
-h, --help Print usage | |
________EOF | |
} | |
while [ -n "$1" ]; do | |
case "$1" in | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
esac | |
shift | |
done | |
cat << '____EOF' | |
[ | |
{ "user": "my-docker-id", "name": "my-debian-image", "tag": "latest", "path": "folder/with/Dockerfile", "pull": "true" }, | |
{ "user": "my-docker-id", "name": "my-other-debian-image", "tag": "latest", "path": "relative/path/to/Dockerfile/directory", "pull": "false" }, | |
{ "user": "my-docker-id", "name": "yet-another-image", "tag": "local", "path": "/absolute/path/to/Dockerfile/directory", "pull": "false", | |
"add": [ "/external/files/required/by/Dockerfile", "relative/path/to/db.json/" ] } | |
] | |
____EOF | |
return 0 | |
} | |
db_pull() { | |
help() { | |
cat << ________EOF | |
Usage: $prg db_pull [OPTIONS] DB [IMAGE...] | |
Pull (all) images stored in database from Docker Hub | |
Options: | |
--tag TAG Override tag from database | |
--debug Print commands issued by $prg | |
-h, --help Print usage | |
________EOF | |
} | |
local _tag="" | |
local _db="" | |
local _imgs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg db_pull" requires at least 1 argument(s). | |
See '$prg db_pull --help'. | |
Usage: $prg db_pull [OPTIONS] DB [IMAGE...] | |
Pull (all) images stored in database from Docker Hub | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--tag") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: --tag" | |
return 255 | |
fi | |
_tag="$2" | |
shift | |
;; | |
"--debug") | |
_debug="yes" | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_db="$1" | |
shift | |
_imgs="$*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
pull_image() { | |
local _user="$1" | |
local _name="$2" | |
local _tag="$3" | |
local _path="$4" | |
local _add="$5" | |
local _pull="$6" | |
local _override_tag="$7" | |
if [ -n "$_override_tag" ]; then | |
_tag="$_override_tag" | |
fi | |
echo "Pulling $_user/$_name:$_tag" | |
docker pull "$_user/$_name:$_tag" | |
} | |
_test_db "$_db" | |
_foreach_image_in_db "$_db" "$_imgs" pull_image "$_tag" | |
} | |
db_push() { | |
help() { | |
cat << ________EOF | |
Usage: $prg db_push [OPTIONS] DB [IMAGE...] | |
Push (all) images stored in database to Docker Hub | |
Options: | |
--tag TAG Override tag from database | |
--debug Print commands issued by $prg | |
-h, --help Print usage | |
________EOF | |
} | |
local _tag="" | |
local _db="" | |
local _imgs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg db_push" requires at least 1 argument(s). | |
See '$prg db_push --help'. | |
Usage: $prg db_push [OPTIONS] DB [IMAGE...] | |
Push (all) images stored in database to Docker Hub | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--tag") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: --tag" | |
return 255 | |
fi | |
_tag="$2" | |
shift | |
;; | |
"--debug") | |
_debug="yes" | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_db="$1" | |
shift | |
_imgs="$*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
push_image() { | |
local _user="$1" | |
local _name="$2" | |
local _tag="$3" | |
local _path="$4" | |
local _add="$5" | |
local _pull="$6" | |
local _override_tag="$7" | |
if [ -n "$_override_tag" ]; then | |
_tag="$_override_tag" | |
fi | |
echo "Pushing $_user/$_name:$_tag" | |
docker push "$_user/$_name:$_tag" | |
} | |
_test_db "$_db" | |
docker login || { | |
error "login failed." | |
return 255 | |
} | |
_foreach_image_in_db "$_db" "$_imgs" push_image "$_tag" | |
} | |
rm() { | |
help() { | |
cat << ________EOF | |
Usage: $prg rm [OPTIONS] [CONTAINER...] | |
Remove one or more containers | |
Options: | |
--debug Print commands issued by $prg | |
-a, --all Remove all existing containers | |
-l, --latest Remove latest created container | |
-o OPTION Pass additional options to docker | |
-h, --help Print usage | |
________EOF | |
} | |
local _all="no" | |
local _latest="no" | |
local _options="" | |
local _ctnrs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg rm" requires at least 1 argument(s). | |
See '$prg rm --help'. | |
Usage: $prg rm [OPTIONS] [CONTAINER...] | |
Remove one or more containers | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--debug") | |
_debug="yes" | |
;; | |
"-a"|"--all") | |
_all="yes" | |
;; | |
"-l"|"--latest") | |
_latest="yes" | |
;; | |
"-o") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: -o" | |
return 255 | |
fi | |
_options="$_options $2" | |
shift | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_ctnrs="$_ctnrs $*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
local _cmd="docker rm " | |
_cmd="$_cmd $_options" | |
if [ "$_all" = "yes" ]; then | |
local _leftover | |
_leftover="$(docker ps -aq)" | |
[ "$_leftover" != "" ] && _ctnrs="$_ctnrs $_leftover" | |
fi | |
if [ "$_latest" = "yes" ]; then | |
local _leftover | |
_leftover="$(docker ps -q -l)" | |
[ "$_leftover" != "" ] && _ctnrs="$_ctnrs $_leftover" | |
fi | |
if [ "$(echo "$_ctnrs" | tr -d '[:space:]')" = "" ]; then | |
echo "No containers found." | |
return 0 | |
fi | |
_cmd="$_cmd $_ctnrs " | |
( | |
[ "$_debug" = "yes" ] && set -x | |
# shellcheck disable=2086 | |
eval $_cmd | |
) | |
} | |
rmi() { | |
help() { | |
cat << ________EOF | |
Usage: $prg rmi [OPTIONS] [IMAGE...] | |
Remove one or more images | |
Options: | |
--all Remove all images | |
--debug Print commands issued by $prg | |
--untagged Remove all untagged images | |
-o OPTION Pass additional options to docker | |
-h, --help Print usage | |
________EOF | |
} | |
local _all="no" | |
local _untagged="no" | |
local _options="" | |
local _imgs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg rmi" requires at least 1 argument(s). | |
See '$prg rmi --help'. | |
Usage: $prg rmi [OPTIONS] [IMAGE...] | |
Remove one or more images | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--all") | |
_all="yes" | |
;; | |
"--debug") | |
_debug="yes" | |
;; | |
"--untagged") | |
_untagged="yes" | |
;; | |
"-o") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: -o" | |
return 255 | |
fi | |
_options="$_options $2" | |
shift | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_imgs="$_imgs $*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
if [ "$_all" = "yes" ]; then | |
docker image prune --force | |
fi | |
local _cmd="docker rmi " | |
_cmd="$_cmd $_options" | |
if [ "$_all" = "yes" ]; then | |
local _ui | |
_ui="$(docker images | tail -n +2 | grep -v "^<none>" | awk '{ print $1 ":" $2 }' | grep -v -e '.*\:<none>$')" | |
if [ "$_ui" = "" ] && [ "$_imgs" = "" ]; then | |
return 0 | |
fi | |
_imgs="$_imgs $_ui" | |
fi | |
if [ "$_untagged" = "yes" ] || [ "$_all" = "yes" ]; then | |
#Ref.: http://jimhoskins.com/2013/07/27/remove-untagged-docker-images.html | |
local _ui | |
_ui="$(docker images | tail -n +2 | grep "^<none>" | awk '{ print $3 }')" | |
if [ "$_ui" = "" ] && [ "$_imgs" = "" ]; then | |
return 0 | |
fi | |
_imgs="$_imgs $_ui" | |
fi | |
if [ "$_imgs" = "" ]; then | |
error "No images specified." | |
return 255 | |
fi | |
_cmd="$_cmd $_imgs " | |
( | |
[ "$_debug" = "yes" ] && set -x | |
# shellcheck disable=2086 | |
eval $_cmd | |
) | |
} | |
save() { | |
help() { | |
cat << ________EOF | |
Usage: $prg save [OPTIONS] [IMAGE...] | |
Save one or more images to a tar archive (streamed to STDOUT by default) | |
Options: | |
--debug Print commands issued by $prg | |
-a, --all Save all available images | |
--tagged Only save tagged images | |
-o OPTION Pass additional options to docker | |
-h, --help Print usage | |
________EOF | |
} | |
local _all="no" | |
local _tagged="no" | |
local _options="" | |
local _imgs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg save" requires at least 1 argument(s). | |
See '$prg save --help'. | |
Usage: $prg save [OPTIONS] [IMAGE...] | |
Save one or more images to a tar archive (streamed to STDOUT by default) | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--debug") | |
_debug="yes" | |
;; | |
"-a"|"--all") | |
_all="yes" | |
;; | |
"--tagged") | |
_tagged="yes" | |
;; | |
"-o") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: -o" | |
return 255 | |
fi | |
_options="$_options $2" | |
shift | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_imgs="$_imgs $*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
local _cmd="docker save " | |
_cmd="$_cmd $_options" | |
if [ "$_all" = "yes" ]; then | |
local _ai | |
_ai="$(docker images -q | uniq)" | |
if [ "$_ai" = "" ]; then | |
error "No images found." | |
return 255 | |
fi | |
_imgs="$_imgs $_ai" | |
fi | |
if [ "$_tagged" = "yes" ] && [ "$_all" = "no" ]; then | |
local _ti | |
_ti="$(docker images | tail -n +2 | grep -v "^<none>" | awk '{ print $1 ":" $2 }' | grep -v -e '.*\:<none>$')" | |
_imgs="$_imgs $_ti" | |
fi | |
if [ "$_imgs" = "" ]; then | |
error "No image specified." | |
return 255 | |
fi | |
_cmd="$_cmd $_imgs " | |
( | |
[ "$_debug" = "yes" ] && set -x | |
# shellcheck disable=2086 | |
eval $_cmd | |
) | |
} | |
start() { | |
help() { | |
cat << ________EOF | |
Usage: $prg start [OPTIONS] [CONTAINER...] | |
Start one or more containers | |
Options: | |
--debug Print commands issued by $prg | |
-a, --all Start all containers | |
-l, --latest Start latest created container | |
-o OPTION Pass additional options to docker | |
-h, --help Print usage | |
________EOF | |
} | |
local _all="no" | |
local _latest="no" | |
local _options="" | |
local _ctnrs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg start" requires at least 1 argument(s). | |
See '$prg start --help'. | |
Usage: $prg start [OPTIONS] [CONTAINER...] | |
Start one or more containers | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--debug") | |
_debug="yes" | |
;; | |
"-a"|"--all") | |
_all="yes" | |
;; | |
"-l"|"--latest") | |
_latest="yes" | |
;; | |
"-o") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: -o" | |
return 255 | |
fi | |
_options="$_options $2" | |
shift | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_ctnrs="$_ctnrs $*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
local _cmd="docker start " | |
_cmd="$_cmd $_options" | |
if [ "$_all" = "yes" ]; then | |
local _ac | |
_ac="$(docker ps -q)" | |
if [ "$_ac" = "" ]; then | |
error "No container found." | |
return 255 | |
fi | |
_ctnrs="$_ctnrs $_ac" | |
fi | |
if [ "$_latest" = "yes" ]; then | |
local _lc | |
_lc="$(docker ps -q -l)" | |
if [ "$_lc" = "" ]; then | |
error "No container found." | |
return 255 | |
fi | |
_ctnrs="$_ctnrs $_lc" | |
fi | |
if [ "$_ctnrs" = "" ]; then | |
error "No container specified." | |
return 255 | |
fi | |
_cmd="$_cmd $_ctnrs " | |
( | |
[ "$_debug" = "yes" ] && set -x | |
# shellcheck disable=2086 | |
eval $_cmd | |
) | |
} | |
stop() { | |
help() { | |
cat << ________EOF | |
Usage: $prg stop [OPTIONS] [CONTAINER...] | |
Stop one or more containers | |
Options: | |
--debug Print commands issued by $prg | |
-a, --all Stop all containers | |
-l, --latest Stop latest created container | |
-o OPTION Pass additional options to docker | |
-h, --help Print usage | |
________EOF | |
} | |
local _all="no" | |
local _latest="no" | |
local _options="" | |
local _ctnrs="" | |
local _debug="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg stop" requires at least 1 argument(s). | |
See '$prg stop --help'. | |
Usage: $prg stop [OPTIONS] [CONTAINER...] | |
Stop one or more containers | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--debug") | |
_debug="yes" | |
;; | |
"-a"|"--all") | |
_all="yes" | |
;; | |
"-l"|"--latest") | |
_latest="yes" | |
;; | |
"-o") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: -o" | |
return 255 | |
fi | |
_options="$_options $2" | |
shift | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
_ctnrs="$_ctnrs $*" | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
local _cmd="docker stop " | |
_cmd="$_cmd $_options" | |
if [ "$_all" = "yes" ]; then | |
local _ac | |
_ac="$(docker ps -q)" | |
if [ "$_ac" = "" ]; then | |
error "No container found." | |
return 255 | |
fi | |
_ctnrs="$_ctnrs $_ac" | |
fi | |
if [ "$_latest" = "yes" ]; then | |
local _lc | |
_lc="$(docker ps -q -l)" | |
if [ "$_lc" = "" ]; then | |
error "No container found." | |
return 255 | |
fi | |
_ctnrs="$_ctnrs $_lc" | |
fi | |
if [ "$_ctnrs" = "" ]; then | |
error "No container specified." | |
return 255 | |
fi | |
_cmd="$_cmd $_ctnrs " | |
( | |
[ "$_debug" = "yes" ] && set -x | |
# shellcheck disable=2086 | |
eval $_cmd | |
) | |
} | |
try_attach() { | |
help() { | |
cat << ________EOF | |
Usage: $prg try_attach [OPTIONS] IMAGE [COMMAND] [ARG...] | |
Try to attach to a running container, if a name is assigned to a container in OPTIONS. If no container with this name is | |
found, "docker run IMAGE COMMAND ARG..." will be used to start a new process in a container. With "docker attach" the | |
local standard input, output, and error streams will be attached to the running container. | |
Accepts the same command line arguments in OPTIONS as "docker run". The following options will be handled by this | |
command and not passed to "docker run". | |
Options: | |
--debug Print commands issued by $prg | |
-h, --help Print usage | |
________EOF | |
} | |
local _args="" | |
local _debug="" | |
local _name="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg try_attach" requires at least 1 argument(s). | |
See '$prg try_attach --help'. | |
Usage: $prg try_attach [OPTIONS] IMAGE [COMMAND] [ARG...] | |
Try to attach to a running container, else use "docker run IMAGE COMMAND ARG..." start a new process in a container | |
first. | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--debug") | |
_debug="yes" | |
;; | |
"--name") | |
if [ -z "$2" ]; then | |
error "flag is missing arg: $1" | |
return 255 | |
fi | |
_name="$2" | |
_args="$_args '$1' '$2'" | |
shift | |
;; | |
"--name="*) | |
_name="$(echo "$1" | sed -e "s/^--name=//")" | |
_args="$_args '$1'" | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
*) | |
_args="$_args '$1'" | |
;; | |
esac | |
shift | |
done | |
( | |
[ "$_debug" = "yes" ] && set -x | |
if [ -z "$_name" ] || [ -z "$(docker container ls -a -q "--filter=name=^$_name\$")" ]; then | |
# no name given or container does not exist | |
eval docker run "$_args" | |
else | |
# container exists | |
if [ -z "$(docker container ls -a -q "--filter=name=$_name" --filter=status=running)" ]; then | |
# container has exited | |
docker start "$_name" | |
fi | |
docker attach "$_name" | |
fi | |
) | |
} | |
try_exec() { | |
help() { | |
cat << ________EOF | |
Usage: $prg try_exec [OPTIONS] IMAGE COMMAND [ARG...] | |
When a container with the name assigned in OPTIONS is found, then use "docker exec COMMAND ARG..." to execute a process | |
in the running container and to attach local standard input, output, and error streams to the running container. If no | |
container with this name can be found, then "docker run --tty --interactive --detach IMAGE /bin/sh" will be used to run | |
and detach from a container before running "docker exec". | |
Options: | |
--debug Print commands issued by $prg | |
--exec-option [OPTION...] -- Options passed to "docker exec". | |
Terminated with double dashes (--). | |
--run-option [OPTION...] -- Options passed to "docker run". | |
Terminated with double dashes (--). | |
-h, --help Print usage | |
________EOF | |
} | |
local _args="" | |
local _command="" | |
local _debug="" | |
local _exec_options="" | |
local _image="" | |
local _name="" | |
local _run_options="" | |
if [ $# -eq 0 ]; then | |
stderr << ________EOF | |
"$prg try_exec" requires at least 1 argument(s). | |
See '$prg try_exec --help'. | |
Usage: $prg try_exec [OPTIONS] IMAGE COMMAND [ARG...] | |
Try to use "docker exec COMMAND ARG..." to a new process in a container. When container has not been started, then run | |
and detach from a container first. | |
________EOF | |
return 255 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"--debug") | |
_debug="yes" | |
;; | |
"--exec-option") | |
if [ -z "$2" ]; then | |
error "arg is missing terminator (--): $1" | |
return 255 | |
fi | |
while [ -n "$2" ]; do | |
case "$2" in | |
--) | |
shift | |
break | |
;; | |
*) | |
_exec_options="$_exec_options '$2'" | |
;; | |
esac | |
shift | |
done | |
;; | |
"--run-option") | |
if [ -z "$2" ]; then | |
error "arg is missing terminator (--): $1" | |
return 255 | |
fi | |
while [ -n "$2" ]; do | |
case "$2" in | |
"-a"|"--attach"|"--attach="*|"-d"|"--detach"|"--detach="*) | |
# we want to detach from "docker run" | |
error "unsupported arg: $1" | |
return 255 | |
;; | |
"--name") | |
if [ -z "$3" ]; then | |
error "flag is missing arg: $2" | |
return 255 | |
fi | |
_name="$3" | |
shift | |
;; | |
"--name="*) | |
_name="$(echo "$2" | sed -e "s/^--name=//")" | |
;; | |
--) | |
shift | |
break | |
;; | |
*) | |
_run_options="$_run_options '$2'" | |
;; | |
esac | |
shift | |
done | |
;; | |
"-h"|"--help") | |
help | |
return 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
return 255 | |
;; | |
*) | |
if [ -z "$2" ]; then | |
error "No command specified" | |
return 255 | |
fi | |
_image="$1" | |
_command="$2" | |
shift 2 | |
while [ -n "$1" ]; do | |
_args="$_args '$1'" | |
shift | |
done | |
set -- 'FOR_NEXT_SHIFT_ONLY' | |
;; | |
esac | |
shift | |
done | |
if [ -z "$_image" ]; then | |
error "No container image specified." | |
return 255 | |
fi | |
# _command cannot be empty | |
if [ -z "$_name" ]; then | |
error "No name of the container specified." | |
return 255 | |
fi | |
( | |
[ "$_debug" = "yes" ] && set -x | |
if [ -z "$(docker container ls -a -q "--filter=name=^$_name\$")" ]; then | |
# container does not exist | |
# shellcheck disable=2086 | |
eval docker run --tty --interactive --detach $_run_options --name "$_name" "$_image" /bin/sh | |
fi | |
if [ -z "$(docker container ls -a -q "--filter=name=$_name" --filter=status=running)" ]; then | |
# container has exited | |
docker start "$_name" | |
fi | |
# shellcheck disable=2086 | |
eval docker exec $_exec_options "$_name" "$_command" $_args | |
) | |
} | |
if [ $# -eq 0 ]; then | |
help | |
exit 1 | |
fi | |
while [ -n "$1" ]; do | |
case "$1" in | |
"attach"|"db_add_tag"|"db_build"|"db_example"|"db_pull"|"db_push"|\ | |
"rm"|"rmi"|"save"|"start"|"stop"|"try_attach"|"try_exec"|"help") | |
("$@") | |
exit $? | |
;; | |
"-v"|"--version") | |
version | |
exit 0 | |
;; | |
"-h"|"--help") | |
help | |
exit 0 | |
;; | |
-*) | |
error "unknown flag: $1" | |
exit 1 | |
;; | |
*) | |
error "unknown command: $1" | |
exit 1 | |
;; | |
esac | |
shift | |
done | |
exit $? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment