235 lines
4.3 KiB
Bash
Executable File
235 lines
4.3 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
set -eo pipefail
|
|
|
|
# snippet from https://github.com/mkropat/sh-realpath
|
|
realpath() {
|
|
canonicalize_path "$(resolve_symlinks "$1")"
|
|
}
|
|
resolve_symlinks() {
|
|
_resolve_symlinks "$1"
|
|
}
|
|
_resolve_symlinks() {
|
|
_assert_no_path_cycles "$@" || return
|
|
local dir_context path
|
|
path=$(readlink -- "$1")
|
|
if [ $? -eq 0 ]; then
|
|
dir_context=$(dirname -- "$1")
|
|
_resolve_symlinks "$(_prepend_dir_context_if_necessary "$dir_context" "$path")" "$@"
|
|
else
|
|
printf '%s\n' "$1"
|
|
fi
|
|
}
|
|
_prepend_dir_context_if_necessary() {
|
|
if [ "$1" = . ]; then
|
|
printf '%s\n' "$2"
|
|
else
|
|
_prepend_path_if_relative "$1" "$2"
|
|
fi
|
|
}
|
|
_prepend_path_if_relative() {
|
|
case "$2" in
|
|
/* ) printf '%s\n' "$2" ;;
|
|
* ) printf '%s\n' "$1/$2" ;;
|
|
esac
|
|
}
|
|
_assert_no_path_cycles() {
|
|
local target path
|
|
target=$1
|
|
shift
|
|
for path in "$@"; do
|
|
if [ "$path" = "$target" ]; then
|
|
return 1
|
|
fi
|
|
done
|
|
}
|
|
canonicalize_path() {
|
|
if [ -d "$1" ]; then
|
|
_canonicalize_dir_path "$1"
|
|
else
|
|
_canonicalize_file_path "$1"
|
|
fi
|
|
}
|
|
_canonicalize_dir_path() {
|
|
(cd "$1" 2>/dev/null && pwd -P)
|
|
}
|
|
_canonicalize_file_path() {
|
|
local dir file
|
|
dir=$(dirname -- "$1")
|
|
file=$(basename -- "$1")
|
|
(cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
|
|
}
|
|
|
|
. ~/.config/contain
|
|
|
|
if [[ -f "$(which docker 2>/dev/null)" ]]; then
|
|
runtime=docker
|
|
elif [[ -f "$(which podman 2>/dev/null)" ]]; then
|
|
runtime=podman
|
|
runtime_extra_opts="$runtime_extra_opts--userns=keep-id "
|
|
fi
|
|
|
|
if $runtime info | grep -iq selinux; then
|
|
selinux_enabled=true
|
|
else
|
|
selinux_enabled=false
|
|
fi
|
|
|
|
OPTIND=1
|
|
|
|
label="${0##*/}=true"
|
|
labels="--label $label "
|
|
env="--env TERM --env CONTAIN=true "
|
|
workdir=""
|
|
delete=""
|
|
name=""
|
|
ports=""
|
|
host=""
|
|
volumes=""
|
|
image="$DEFAULT_IMAGE"
|
|
tag="$DEFAULT_TAG"
|
|
|
|
show_help() {
|
|
cat << EOF
|
|
Usage: ${0##*/} [-xwo] [-n NAME] [-p PORT]... [-v LIST]... [-i IMAGE] [-t TAG] [CMD]...
|
|
${0##*/} -l
|
|
${0##*/} -a NAME
|
|
${0##*/} -e NAME [CMD]...
|
|
${0##*/} -h
|
|
Starts an environment container. If CMD is specified, starts CMD instead of a shell.
|
|
|
|
-x delete Docker container after exit. will loose data
|
|
-w forward \$PWD into $CONTAIN_HOME/src, and start there
|
|
-o use host networking instead
|
|
-n NAME give container a NAME
|
|
-p PORT forward host PORT to container PORT
|
|
-v LIST mount volume LIST. specify as LOCAL:MOUNT
|
|
-i IMAGE use IMAGE as container image instead
|
|
-t TAG use TAG as container tag instead
|
|
|
|
-l list running containers and exit
|
|
-u pull image and exit
|
|
-a NAME attach to a running container
|
|
-e NAME execute zsh or CMD on a running container
|
|
-h display this help and exit
|
|
|
|
EOF
|
|
}
|
|
|
|
list_running() {
|
|
$runtime ps --all \
|
|
--filter label="$label" \
|
|
--format "table {{.Names}}\t{{.RunningFor}}\t{{.Ports}}\t{{.Command}}"
|
|
}
|
|
|
|
pull_image() {
|
|
$runtime pull \
|
|
$image:$tag
|
|
}
|
|
|
|
while getopts "xwon:p:v:i:t:lua:e:h" opt; do
|
|
case "$opt" in
|
|
x)
|
|
delete="--rm "
|
|
;;
|
|
w)
|
|
workdir="--workdir $CONTAIN_HOME/src/ "
|
|
if $selinux_enabled; then
|
|
volume_opts=":z"
|
|
fi
|
|
mount="$(realpath "$PWD")"
|
|
volumes="$volumes--volume \"$mount:$CONTAIN_HOME/src/$volume_opts\" "
|
|
;;
|
|
o)
|
|
host="--net host "
|
|
;;
|
|
n)
|
|
name="--name $OPTARG --hostname $OPTARG "
|
|
;;
|
|
p)
|
|
ports="$ports--publish $OPTARG:$OPTARG "
|
|
;;
|
|
v)
|
|
if $selinux_enabled; then
|
|
volume_opts=":z"
|
|
fi
|
|
volumes="$volumes--volume $OPTARG$volume_opts "
|
|
;;
|
|
i)
|
|
image="$OPTARG"
|
|
;;
|
|
t)
|
|
tag="$OPTARG"
|
|
;;
|
|
l)
|
|
list_running
|
|
exit 0
|
|
;;
|
|
u)
|
|
pull_image
|
|
exit 0
|
|
;;
|
|
a)
|
|
mode_attach="true"
|
|
name="$OPTARG"
|
|
;;
|
|
e)
|
|
mode_execute="true"
|
|
name="$OPTARG"
|
|
;;
|
|
h)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
:)
|
|
echo "Option -$OPTARG requires an argument." >&2
|
|
show_help
|
|
exit 1
|
|
;;
|
|
\?)
|
|
echo "Invalid option: -$OPTARG" >&2
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
shift $((OPTIND-1))
|
|
[ "$1" = "--" ] && shift
|
|
|
|
if [ "$ports" = "\n\t" ]; then
|
|
ports=""
|
|
fi
|
|
|
|
if [ "$mode_attach" = "true" ]; then
|
|
$runtime attach \
|
|
$name
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$mode_execute" = "true" ]; then
|
|
cmd="$@"
|
|
if [ -z "$@" ]; then
|
|
cmd="/bin/zsh"
|
|
fi
|
|
$runtime exec --interactive --tty \
|
|
$name \
|
|
$cmd
|
|
exit 0
|
|
fi
|
|
|
|
cmd="\
|
|
$runtime run --interactive --tty \
|
|
$runtime_extra_opts\
|
|
$labels$env\
|
|
$delete\
|
|
$name\
|
|
$ports$host\
|
|
$workdir$volumes\
|
|
$image:$tag\
|
|
$@ \
|
|
"
|
|
|
|
echo Running: $cmd
|
|
exec sh -c "exec $cmd"
|