Skip to content

Instantly share code, notes, and snippets.

@TomCrypto
Last active October 25, 2016 09:09
Show Gist options
  • Save TomCrypto/e8eaa2ee84694768403d43421ca0241c to your computer and use it in GitHub Desktop.
Save TomCrypto/e8eaa2ee84694768403d43421ca0241c to your computer and use it in GitHub Desktop.
A convenient Docker build environment control script
#!/usr/bin/env bash
# NOTE: make your dockerfile define the WITHIN_CONTAINER envvar:
# ENV WITHIN_CONTAINER yes
if [ ! -z ${WITHIN_CONTAINER+x} ]; then
printf "$0: Already within a container.\n" && exit 126
fi
DOCKER=$(which docker)
IMAGE_NAME="your_project_name"
function filter_clean {
DELETE="$1"
FILTER="$2"
container=$(${DOCKER} ps -a ${FILTER} \
| grep "${IMAGE_NAME}:latest" \
| awk '{print $1}')
if [ ! -z ${container} ]; then
if [ "${DELETE}" = true ]; then
${DOCKER} stop ${container} > /dev/null
fi
${DOCKER} rm ${container} > /dev/null
fi
return 0
}
function command_create {
GITROOT="$1"
ENVROOT="$2"
OPTIONS="${@:3}"
# if it's not running, delete & rebuild it
filter_clean false "--filter status=exited"
if [ -z "$(${DOCKER} ps | grep "${IMAGE_NAME}:latest")" ]; then
${DOCKER} build -t ${IMAGE_NAME}:latest ${ENVROOT} &&
${DOCKER} run -dti --user=$(id -u):$(id -g) \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/localtime:/etc/localtime:ro \
-v ${GITROOT}:/home/your_project_name/git \
--name="${IMAGE_NAME}" ${OPTIONS} ${IMAGE_NAME}
fi
}
function command_delete {
filter_clean true
}
function command_attach {
${DOCKER} exec -it ${IMAGE_NAME} bash
return 0
}
function command_remote {
${DOCKER} exec ${IMAGE_NAME} $@
return 0
}
function usage {
printf "Usage:\n"
printf "\t$0 create [git root] [env root] [docker run options ...]\n"
printf "\t$0 delete\n"
printf "\t$0 attach\n"
printf "\t$0 remote [...]\n"
return 127
}
COMMAND="$1" && shift
case ${COMMAND} in
create)
if [[ $# -gt 2 ]]; then
command_create $@
else
usage
fi
;;
delete)
if [[ $# -eq 0 ]]; then
command_delete
else
usage
fi
;;
attach)
if [[ $# -eq 0 ]]; then
command_attach
else
usage
fi
;;
remote)
if [[ $# -gt 0 ]]; then
command_remote $@
else
usage
fi
;;
*)
usage
;;
esac
@TomCrypto
Copy link
Author

TomCrypto commented Oct 8, 2016

I made this useful script for spinning up a Docker environment which I use to interactively build my code. What it does is create your container based on your Dockerfile, mounts a working directory (GITROOT, usually the root of your repository) into the container, as well as some other useful stuff (/etc/localtime, /etc/passwd). This is done by invoking ./control.sh create, it is safe to call it multiple times.

To drop into a shell in your container, just do ./control.sh attach. To execute a command in your container without getting a shell, do ./control.sh remote <your command> your args.... You can use ./control.sh delete to stop and delete the container.

The create command takes at least two arguments: the working directory (which will be mounted into the container), the ENVROOT (ideally this will be a folder containing only your Dockerfile, any files needed by your image and maybe this script, since you don't need to upload much more to the daemon) and any further arguments are forwarded to docker run.

Your dockerfile should have the following in it ideally:

RUN mkdir /home/your_project_name/git
WORKDIR /home/your_project_name/git
CMD bash

That way you still have a proper home directory in your container, which contains a folder git where your repository is mounted.

This integrates really well with a makefile, as you can make a rule that lets e.g. make env drop you into a shell in your build environment.

@TomCrypto
Copy link
Author

Small revision: if the create command is invoked while the container exists but is stopped, the container is deleted and rebuilt (quickly since it's probably in cache). This is useful if the docker run failed for some reason, or after rebooting. The alternative is to skip building if it's there but not running and just start it directly, but better be safe than sorry since building from cache is so cheap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment