Created
February 20, 2017 08:38
-
-
Save benweidig/5e60a48ea0d5c271b8ac1b56735be546 to your computer and use it in GitHub Desktop.
(Blog) docker-runner.sh
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 | |
# Author: Benjamin Weidig <ben@netzgut.net> | |
# Version: 1 (2017-02-19) | |
# A helper shell script for starting a Docker container in a more flexible way. | |
# A container might not start if all the linked containers or ports are not | |
# available, so now we are able to specify optional resources. | |
# This script is used at Netzgut to start desktop applications with Docker. | |
# REQUIRED: The image you want to use | |
IMAGE="desktop/eclipse" | |
# REQUIRED: The name of the container, needed for identification | |
CONTAINER_NAME=eclipse | |
# OPTIONAL: Connect to specific docker network | |
NETWORK="docker_dev" | |
# Removes the container if it's already running. | |
# This might be a problem for you because you could destroy unsaved progress. | |
# If "0" then the container will only be removed if not already running and no | |
# new container will be started. | |
KILL_IF_RUNNING=1 | |
# OPTIONAL: Additional arguments that will just be passed directly to docker | |
ARGS=() | |
# OPTIONAL: This volumes will be created if they don't exist. | |
# Why? Because if the docker-engine would create them they would | |
# be owned by root. That's not necessary a problem but the files | |
# will be easier to use outside of the container this way. | |
# CAVEAT: No "~"-expansion is supported, so use $HOME | |
VOLUMES_ENSURE=( | |
$HOME/code/eclipse/:/home/docker/workspaces | |
$HOME/code:/home/docker/code | |
$HOME/.docker-data/eclipse:/home/docker/.eclipse | |
$HOME/.m2/repository:/home/docker/.m2/repository | |
) | |
# OPTIONAL: This volumes will be mounted "normally" without any checks from us. | |
# CAVEAT: No "~"-expansion is supported, so use $HOME | |
VOLUMES=( | |
$HOME/.dotfiles/gitconfig:/home/docker/.gitconfig:ro | |
$HOME/.dotfiles/hgrc:/home/docker/.hgrc:ro | |
$HOME/.hgext/hgflow.py:/home/docker/.hgext/hgflow.py:ro | |
$HOME/.hgext/mercurial_keyring.py:/home/docker/.hgext/mercurial_keyring.py:ro | |
$HOME/.dotfiles/m2/settings.xml:/home/docker/.m2/settings.xml:ro | |
/etc/localtime:/etc/localtime:ro | |
/etc/timezone:/etc/timezone:ro | |
/tmp/.X11-unix:/tmp/.X11-unix | |
) | |
# OPTIONAL: Links to other containers that are not checked if they are actually running. | |
# Normally that's a problem, except when you run in a network that actually defines the | |
# container. | |
LINKS=( | |
mongo:mongo | |
mysql:mysql | |
) | |
# OPTIONAL: These links are optional and won't be linked if not available. | |
LINKS_OPTIONAL=( | |
postgres:postgres | |
rabbitmq:rabbitmq | |
) | |
# OPTIONAL: Required ports. We won't do any checks, let the docker-engine do its work. | |
PORTS=( | |
8080:8080 | |
8081:8081 | |
) | |
# OPTIONAL: These ports are optional. We check with netstat if they are available. | |
PORTS_OPTIONAL=( | |
8443:8443 | |
8888:8888 | |
) | |
# OPTIONAL: Sets environment variables. | |
ENVS=( | |
"DISPLAY=$DISPLAY" | |
SWT_GTK3=0 | |
MEM_XMS=512m | |
MEM_XMX=3G | |
MEM_MAX_PERM_SIZE=3G | |
) | |
############################################################################### | |
############################################################################### | |
#### DO NOT CHANGE BELOW THIS BLOCK ####### DO NOT CHANGE BELOW THIS BLOCK #### | |
############################################################################### | |
############################################################################### | |
# Notification system: The MESSAGES will be displayed to | |
# e.g. inform the user about the actual start parameters | |
# if not all optionals could be fulfilled. | |
MESSAGES=() | |
function notify { | |
if [ ! -z "$MESSAGES" ]; then | |
notify-send "$1" "${MESSAGES[@]}" | |
fi | |
} | |
############################################################################### | |
# Step 1: Remove a previously running container by its name. # | |
############################################################################### | |
if [ $KILL_IF_RUNNING -eq 1 ]; then | |
echo "KILLING" | |
docker rm -f $CONTAINER_NAME 2> /dev/null | |
else | |
echo "NO KILLING" | |
docker top $CONTAINER_NAME &>/dev/null | |
if [ $? -eq 0 ]; then | |
MESSAGES+="Container is already running and KILL_IF_RUNNING=0" | |
notify "Couldn't start container $CONTAINER_NAME" | |
exit -1 | |
fi | |
fi | |
############################################################################### | |
# Step 2: VOLUMES # | |
############################################################################### | |
ALL_VOLUMES=() | |
# Check the volumes that might need creation. | |
if [ ! -z "$VOLUMES_ENSURE" ]; then | |
VOLUMES_MESSAGE=0 | |
for VOLUME in ${VOLUMES_ENSURE[@]} | |
do | |
HOST_VOLUME=${VOLUME%:*} | |
if [ ! -d $HOST_VOLUME ]; then | |
mkdir -p $HOST_VOLUME 2> /dev/null | |
if [ VOLUMES_MESSAGE -eq 0 ]; then | |
MESSAGES+="\nCreated Volumes:" | |
VOLUMES_MESSAGE=1 | |
fi | |
MESSAGES+="\n- $HOST_VOLUME" | |
fi | |
ALL_VOLUMES+=($VOLUME) | |
done | |
fi | |
# If we got any other volumes add them to the all volumes, too. | |
if [ ! -z "$VOLUMES" ]; then | |
ALL_VOLUMES=("${ALL_VOLUMES[@]}" "${VOLUMES[@]}") | |
fi | |
############################################################################### | |
# Step 3: LINKS # | |
############################################################################### | |
ALL_LINKS=() | |
# Check if the optional links are running. | |
if [ ! -z "$LINKS_OPTIONAL" ]; then | |
LINKS_MESSAGE=0 | |
for LINK in ${LINKS_OPTIONAL[@]}; do | |
HOST_LINK=${LINK%:*} | |
docker top $HOST_LINK &>/dev/null | |
if [ $? -eq 0 ]; then | |
ALL_LINKS+=($LINK) | |
else | |
if [[ $LINKS_MESSAGE -eq 0 ]]; then | |
MESSAGES+="\nUnavailable linked containers:" | |
LINKS_MESSAGE=1 | |
fi | |
MESSAGES+="\n- $HOST_LINK" | |
fi | |
done | |
fi | |
# Add required links to all links. | |
if [ ! -z "$LINKS" ]; then | |
ALL_LINKS=("${ALL_LINKS[@]}" "${LINKS[@]}") | |
fi | |
############################################################################### | |
# Step 4: PORTS # | |
############################################################################### | |
ALL_PORTS=() | |
# Check if the optional ports are available. | |
if [ ! -z "$PORTS_OPTIONAL" ]; then | |
PORTS_MESSAGE=() | |
for PORT in ${PORTS_OPTIONAL[@]}; do | |
HOST_PORT=${PORT%:*} | |
OUT=$(netstat -lnt | awk -v port=$HOST_PORT '$6 == "LISTEN" && $4 ~ port') | |
if [[ -z $OUT ]] | |
then | |
ALL_PORTS+=($PORT) | |
else | |
if [[ $PORTS_MESSAGE -eq 0 ]]; then | |
MESSAGES+="\nUnavailable port:" | |
PORTS_MESSAGE=1 | |
fi | |
MESSAGES+="\n- $HOST_PORT" | |
fi | |
done | |
fi | |
# Add any required ports to the list. | |
if [ ! -z "$PORTS" ]; then | |
ALL_PORTS=("${ALL_PORTS[@]}" "${PORTS[@]}") | |
fi | |
############################################################################### | |
# STEP 5: Build the actual "docker run" arguments # | |
############################################################################### | |
ALL_ARGS=( | |
"--rm" | |
"--name $CONTAINER_NAME") | |
# Add any passthrough arguments | |
if [ ! -z "$ARGS" ]; then | |
ALL_ARGS=("${ALL_ARGS[@]}" "${ARGS[@]}") | |
fi | |
# Add network if set | |
if [ ! -z "$NETWORK" ]; then | |
ALL_ARGS+=("--net $NETWORK") | |
fi | |
# Add all volumes | |
for VOLUME in ${ALL_VOLUMES[@]}; do | |
ALL_ARGS+=("-v $VOLUME") | |
done | |
# Add all links | |
for LINK in ${ALL_LINKS[@]}; do | |
ALL_ARGS+=("--link $LINK") | |
done | |
# Add all ports | |
for PORT in ${ALL_PORTS[@]}; do | |
ALL_ARGS+=("-p $PORT") | |
done | |
# Add environment variables | |
if [ ! -z "$ENVS" ]; then | |
for ENV in ${ENVS[@]}; do | |
ALL_ARGS+=("-e $ENV") | |
done | |
fi | |
# Add image name last | |
ALL_ARGS+=($IMAGE) | |
############################################################################### | |
# Step 6: Notify user and start container | |
############################################################################### | |
notify "Started Container $CONTAINER_NAME" | |
docker run ${ALL_ARGS[@]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment