Skip to content

Instantly share code, notes, and snippets.

@benweidig
Created February 20, 2017 08:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benweidig/5e60a48ea0d5c271b8ac1b56735be546 to your computer and use it in GitHub Desktop.
Save benweidig/5e60a48ea0d5c271b8ac1b56735be546 to your computer and use it in GitHub Desktop.
(Blog) docker-runner.sh
#!/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