Last active
October 25, 2016 09:09
-
-
Save TomCrypto/e8eaa2ee84694768403d43421ca0241c to your computer and use it in GitHub Desktop.
A convenient Docker build environment control script
This file contains 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
#!/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 |
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
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 todocker run
.Your dockerfile should have the following in it ideally:
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.