Skip to content

Instantly share code, notes, and snippets.

@smoser

smoser/README.md

Last active Jul 9, 2020
Embed
What would you like to do?
bootstrap (bs) run (vcs-run)

Docker ubuntu containers are pretty useless by themselves. The expectation is that the user will create a DockerFile and build their own image and push that image somewhere and maintain it.

In 2013 I authored vcs-run as part of cloud-utils. It is installed by default in ubuntu server images, but not in the docker images. :-(. The idea of vcs-run is that you can just invoke something like:

vcs-run https://your.git.server/repo.git bootstrap your-args-here

vcs-run would handle:

  • installing git
  • cloning repo
  • change dir to repo
  • executing bootstrap with your-args-here

Well, since there is nothing inside the ubuntu:20.04 docker image that can do that, we'll have to put it all into the cmdline of shell. Successfully providing complex command lines to a container can be difficult. So to work around bugs in "helpful" infrastructure parsing of string fields into arrays, 'stuffit' here will output a somewhat simple command and uses an environment variable to actually carry the payload. Stuffit then has the following dependencies on an image:

  • apt-get - for getting 'wget' and ca-certificates if not present. (this is actually a dependency of 'bs')
  • base64 - for decoding BS_BLOB
  • sh

So here is how you can enable a ubuntu:20.04 image to do the famous curl | bash bootstrap mechanism.

$ ./stuffit https://gist.githubusercontent.com/smoser/d0e4b583a82a81fdf09bf17c6efc9462/raw/my-bs
BS_URL=https://gist.githubusercontent.com/smoser/d0e4b583a82a81fdf09bf17c6efc9462/raw/my-bs
BS_BLOB=Y29tbWFuZCAtdiB3Z2V0ID4vZGV2L251bGwgMj4mMSB8fCB7CiAgYXB0LWdldCB1cGRhdGUgLXEgJiYKICBERUJJQU5fRlJPTlRFTkQ9bm9uaW50ZXJhY3RpdmUgXAogICAgYXB0LWdldCBpbnN0YWxsIC15IC0tbm8taW5zdGFsbC1yZWNvbW1lbmRzIHdnZXQgY2EtY2VydGlmaWNhdGVzOwp9IHx8IGV4aXQ7CmV4cG9ydCBCU19GSUxFPSR7QlNfRklMRTotL3J1bi9ic307ClsgLXogIiRCU19VUkwiIC1hICQjIC1nZSAxIF0gJiYgeyBCU19VUkw9IiQxIjsgc2hpZnQ7IH0Kd2dldCAiJEJTX1VSTCIgLU8gIiRCU19GSUxFIgpjaG1vZCA3NTUgIiRCU19GSUxFIgpleGVjICIkQlNfRklMRSIgIiRAIgo=
sh -c 'p=$(echo $BS_BLOB | base64 --decode) && exec sh -c "$p" bsblob "$@"'

Now, to run that in docker:

$ docker run \
    --env=BS_URL=https://gist.githubusercontent.com/smoser/d0e4b583a82a81fdf09bf17c6efc9462/raw/my-bs \
    --env=BS_BLOB=Y29tbWFuZCAtdiB3Z2V0ID4vZGV2L251bGwgMj4mMSB8fCB7CiAgYXB0LWdldCB1cGRhdGUgLXEgJiYKICBERUJJQU5fRlJPTlRFTkQ9bm9uaW50ZXJhY3RpdmUgXAogICAgYXB0LWdldCBpbnN0YWxsIC15IC0tbm8taW5zdGFsbC1yZWNvbW1lbmRzIHdnZXQgY2EtY2VydGlmaWNhdGVzOwp9IHx8IGV4aXQ7CmV4cG9ydCBCU19GSUxFPSR7QlNfRklMRTotL3J1bi9ic307ClsgLXogIiRCU19VUkwiIC1hICQjIC1nZSAxIF0gJiYgeyBCU19VUkw9IiQxIjsgc2hpZnQ7IH0Kd2dldCAiJEJTX1VSTCIgLU8gIiRCU19GSUxFIgpjaG1vZCA3NTUgIiRCU19GSUxFIgpleGVjICIkQlNfRklMRSIgIiRAIgo= \
    ubuntu:20.04 \
    sh -c 'p=$(echo $BS_BLOB | base64 --decode) && exec sh -c "$p" bsblob "$@"'

Rancher

I'm able to successfully run a container in rancher using this mechanism. I had problems getting the 'command' to take multiple arguments with double or single quotes. I think it tries to parse them or pass them to sh, but I have not figure out the pattern.

So, just use the 'sh -c' line of 'stuffit' output as above, and then fill in Environment variables BS_URL and BS_BLOB.

sh -c 'p=$(echo $BS_BLOB | base64 --decode) && exec sh -c "$p" bsblob "$@"'
command -v wget >/dev/null 2>&1 || {
apt-get update -q &&
DEBIAN_FRONTEND=noninteractive \
apt-get install -y --no-install-recommends wget ca-certificates;
} || exit;
export BS_FILE=${BS_FILE:-/run/bs};
[ -z "$BS_URL" -a $# -ge 1 ] && { BS_URL="$1"; shift; }
wget "$BS_URL" -O "$BS_FILE" || exit
chmod 755 "$BS_FILE"
exec "$BS_FILE" "$@"
#!/bin/sh
LOG="/run/my-bs.log"
msg() {
echo "$@"
echo "$@" >> "$LOG"
}
: > "$LOG"
msg "HELLO WORLD. I'm up, and am pid $$"
msg "sleeping now for 1d. further output in $LOG."
env
set -x
exec sleep 1d >>"$LOG" 2>&1
#!/bin/sh
fail() { echo "$@" 1>&2; exit 1; }
bsurl="$1"
[ $# -eq 0 ] || shift
bsfile="${BS_FILE:-bs.sh}"
b64=$(base64 --wrap=0 "$bsfile") ||
fail "failed base64 encode $bsfile"
shcode='p=$(echo $BS_BLOB | base64 --decode) && exec sh -c "$p" bsblob "$@"'
ptargs=""
if [ -n "$#" ]; then
ptargs=$(getopt --shell sh --options "" -- -- "$@")
ptargs=${ptargs# -- }
fi
[ -n "$bsurl" ] && printf "BS_URL=%s\n" "$bsurl"
printf "BS_BLOB=%s\n" "$b64"
if [ -z "$ptargs" ]; then
printf "sh -c '%s' bsarg0 %s\n" "$shcode"
else
printf "sh -c '%s' bsarg0 %s\n" "$shcode" "$ptargs"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment