#!/bin/sh # -*- mode: shell-script; sh-basic-offset: 8; tab-width: 8 -*- case ${BASH_VERSION-} in *.*) PATH=/ shopt -s xpg_echo; esac case ${ZSH_VERSION-} in *.*) PATH=/ emulate ksh; esac set -u # expanding unset variable makes non-interactive shell exit immediately set -f # disable pathname expansion by default -- makes e.g. eval more robust set -e # exit on error -- know potential false negatives and positives ! #et -x # s/#/s/ may help debugging (or run /bin/sh -x ... on command line) LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8; export LANG LC_ALL #PATH='/sbin:/usr/sbin:/bin:/usr/bin'; export PATH # XXX If bash finds *this* script by searching PATH... case $0 in */*) ;; *) echo "'$0' does not contain '/'s. try './$0'" >&2; exit 1 esac saved_IFS=$IFS; readonly saved_IFS warn () { for l; do echo "$l"; done; } >&2 die () { for l; do echo "$l"; done; exit 1; } >&2 x () { echo + "$@" >&2; "$@"; } x_env () { echo + "$@" >&2; env "$@"; } x_eval () { echo + "$*" >&2; eval "$*"; } x_exec () { echo + "$@" >&2; exec "$@"; die "exec '$*' failed"; } test $# -gt 0 || { exec >&2; echo echo Usage: $0 '(debian8|ubuntu1604)' echo echo After everything set up a user shell to the given container echo is started "(cwd='$HOME'; X11 should work)." echo echo If container is already running, new shell is started. echo If container exists but is not running it is restarted. echo If image exists but no container, new container is created. echo If image does not exist. It is built. echo Build files are stored in /root/.docker-setup/ in the container. echo exit 1 } case $1 in debian|debian8) shift; set debian8 "$@" name='debian8-notmuch' ;; ubuntu|ubuntu16|ubuntu1604) shift; set ubuntu1604 "$@" name='ubuntu1604-notmuch' ;; *) die "'$1': unsupported container name" esac if status=`exec docker inspect -f '{{.State.Status}}' $name 2>&1` then if test "$status" = running then x_exec docker exec -it "$name" /bin/bash --login else x_exec docker start -i "$name" fi fi run () { test -d /tmp/.X11-unix && xv='-v /tmp/.X11-unix:/tmp/.X11-unix:ro' || xv= x_exec docker run -it -e DISPLAY -e _USER="$USER" --name "$name" \ -h "$name" -v $HOME:/home/$USER ${v:+-v "$v"} --ipc=host "$name" } case $status in *parsing*error*.State.Status*) run; esac # Here if above docker inspect -f '{{.State.Status}}' did not match above, but # Error: No such image or container: ... case $1 in debian8) FROM_HASH=1b01529cc499d51767c62f9fc8083043610546b4e050898809ec54e00dbb1a34 FROM_REF=debian:8.5 ;; ubuntu1604) FROM_HASH=42118e3df429f09ca581a9deb3df274601930e428e452f7e4e9f1833c56a100a FROM_REF=ubuntu:16.04 esac TRUNC_HASH=${FROM_HASH%????????????????????????????????????????????????????} rmtmps () { rm -rf _docker_wip; trap - 0; } rmtmps mkdir _docker_wip # outcomment next line when debugging build trap rmtmps 0 INT HUP TERM exec 3>&1 > _docker_wip/Dockerfile.gen cat < /etc/default/locale \ && apt-get install -y -q build-essential git libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev \ && apt-get -y autoremove && apt-get -y clean # rm -rf /var/lib/apt/lists/ EOF esac # all containers (more may be added...) cat <<'EOF' RUN set -xeu \ && chmod 755 /root \ && exec 3>&1 >>/root/.bash_profile && echo \ && echo 'test ! -f /root/.docker-setup/bash-as-user.sh ||' \ && echo ' . /root/.docker-setup/bash-as-user.sh' \ && exec >>/etc/bash.bashrc && echo \ && echo '# emulate zsh printexitvalue (written from Dockerfile)' \ && echo 'trap '\''echo -n bash: exit $? \\ \\ ; fc -nl -1 -1'\'' ERR' \ && exec 1>&3 3>&- \ && umask 077 \ && mkdir -p /etc/sudoers.d \ && echo '%root ALL= NOPASSWD: ALL' >/etc/sudoers.d/55-wheel-allmighty ADD bash-as-user.sh Dockerfile.gen /root/.docker-setup/ CMD ["/bin/bash", "--login" ] EOF exec >&3 3>&- cat >_docker_wip/bash-as-user.sh <<'EOF' # This file is supposed to be loaded from /root/.bash_profile # when bash is started as login shell (-l or --login). user=${_USER-} unset _USER if test "$user" && test -d /home/"$user" then case $user in *[!-a-z0-9_]*) exit 1; esac grep -q "^$user:" /etc/passwd || { duid=`exec stat -c %u /home/"$user"` useradd -d /home/"$user" -M -u $duid -U -G 0 -s /bin/bash \ -c "user $user" "$user" 2>/dev/null || : } fi # Simple change user which may work as well as gosu(1) if not (better). test -z "$user" || exec perl -e ' my @user = getpwnam $ARGV[0]; chdir $user[7]; $ENV{HOME} = $user[7]; $ENV{USER} = $ARGV[0]; $( = $) = "$user[3] $user[3] 0"; $< = $> = $user[2]; die "setting uids: $!\n" if $!; exec qw"/bin/bash --login";' "$user" unset user EOF ( cd _docker_wip # TIME is used by (GNU) /usr/bin/time (TIMEFORMAT by bash builtin) export TIME='%Us user, %Ss system, %P cpu, %E total (max resident mem %Mk)' export SHELL=/bin/sh x command time docker build -f Dockerfile.gen -t $name . x_exec docker history $name ) rmtmps # run() does exec; auto-eliminating traps run