#!/usr/bin/env bash ZEUS_VERSION="1.2.0" # Define some colours RED="$(tput setaf 1)" GREEN="$(tput setaf 2)" YELLOW="$(tput setaf 3)" BLUE="$(tput setaf 4)" RESET="$(tput sgr0)" logo () { echo "zeus - the utility wrapper for docker, docker-compose, docker-machine and docker-machine-nfs" version echo "" } versionShort () { echo "$ZEUS_VERSION" } version () { echo "zeus version $(versionShort)" } usage () { logo cat < ${YELLOW}Commands:${RESET} ${GREEN}init ${RESET}Initialises Zeus and creates a Zeusfile ${GREEN}create ${RESET}Creates the Docker machine for the first time ${GREEN}up ${RESET}Starts the Docker containers ${GREEN}down ${RESET}Removes the Docker containers ${GREEN}reload ${RESET}Recreates the Docker containers ${GREEN}stop ${RESET}Stops the Docker machine ${GREEN}start ${RESET}Starts the Docker machine ${GREEN}restart ${RESET}Restarts the Docker machine ${GREEN}pull ${RESET}Fetch latest images for the Docker containers ${GREEN}list ${RESET}Lists Docker containers ${GREEN}ssh [container] ${RESET}Connect via SSH to the specified container ${GREEN}info ${RESET}Displays info for your Docker machine ${GREEN}destroy ${RESET}Removes the Docker machine ${GREEN}fix ${RESET}Attempts to fix any SSL or NFS issues ${GREEN}run ${RESET}Runs a command from within a new container ${GREEN}exec ${RESET}Runs a command from within a running container ${GREEN}logs ${RESET}Follows logs from a running container ${GREEN}top ${RESET}Displays CPU, memory, network and disk IO for running containers ${GREEN}scripts ${RESET}Runs scripts in the zeus.d directory on the virtual machine EOF exit } green () { return "${GREEN}$1${RESET}" } echoGreen () { echoZeus "${GREEN}$1${RESET}" } echoRed () { echoZeus "${RED}$1${RESET}" } echoBlank () { echo "" } echoZeus () { echo -e "${BLUE}[zeus]${RESET} $1" } echoError () { echoRed "$1" echoBlank } echoSuccess () { echoGreen "$1" echoBlank } echoPending () { echoZeus "${YELLOW}$1${RESET}" } echoAbort () { echoError "$1\n\nAborting.."; exit 1; } checkMachineRunning () { machine_state=$(docker-machine status $1 2> /dev/null) if [ "Running" != "${machine_state}" ]; then echo "false"; return fi echo "true" } setPropDefaults () { # Gather the env vars we need to run. [ -f $PWD/Zeusfile ] && source $PWD/Zeusfile; [ -z "$ZEUS_NAME" ] && echoAbort "Please set ZEUS_NAME in Zeusfile or ENV." [ -z "$ZEUS_DOMAIN" ] && echoAbort "Please set ZEUS_DOMAIN in Zeusfile or ENV." [ -z "$ZEUS_SHELL" ] && ZEUS_SHELL="bash"; [ -z "$ZEUS_VIRTUALBOX_MEMORY" ] && ZEUS_VIRTUALBOX_MEMORY="1024" [ -z "$ZEUS_VIRTUALBOX_CPU_COUNT" ] && ZEUS_VIRTUALBOX_CPU_COUNT="1" [ "$(checkMachineRunning ${ZEUS_NAME})" = "true" ] && { ZEUS_MACHINE_RUNNING="true" } } ensureCompatible () { # Check running on Darwin # [ "$(uname -s)" == "Darwin" ] || echo "Warning: zeus is for OS X only." # Check all required software is installed. for REQ_BINARY in docker docker-compose docker-machine docker-machine-nfs; do command -v "$REQ_BINARY" >/dev/null 2>&1 || { echoAbort "I require $REQ_BINARY but it's not installed." } done } zeusInit () { [ -f $PWD/Zeusfile ] && echoAbort "Zeusfile already exists." GUESSED_NAME=${PWD##*/} GUESSED_DOMAIN="$GUESSED_NAME.dev" read -p "What is your Docker project name? [$GUESSED_NAME] " ZEUS_NAME read -p "What is your Docker domain name? [$GUESSED_DOMAIN] " ZEUS_DOMAIN [ "$ZEUS_NAME" == "" ] && ZEUS_NAME="$GUESSED_NAME" [ "$ZEUS_DOMAIN" == "" ] && ZEUS_DOMAIN="$GUESSED_DOMAIN" cat >$PWD/Zeusfile < /dev/null; then PROMPT_TEXT=$(echoZeus "Would you like to set a static IP with \`docker-machine-ipconfig\`? [none] ") read -p "$PROMPT_TEXT" ZEUS_STATIC_IP fi [ ! -z "$ZEUS_STATIC_IP" ] && { echoPending "Creating $ZEUS_NAME with IP address $ZEUS_STATIC_IP." } docker-machine create --driver virtualbox \ --virtualbox-memory ${ZEUS_VIRTUALBOX_MEMORY} \ --virtualbox-cpu-count ${ZEUS_VIRTUALBOX_CPU_COUNT} \ ${ZEUS_NAME} [ ! -z "$ZEUS_STATIC_IP" ] && { docker-machine-ipconfig static ${ZEUS_NAME} ${ZEUS_STATIC_IP} } docker-machine-nfs ${ZEUS_NAME} -s="$PWD" if [[ -d "zeus.d" ]]; then dockerScripts fi dockerInfo read -p "Would you like to automatically add this to your hosts file? (y/n) " HOSTS_AUTO_UPDATE case "$HOSTS_AUTO_UPDATE" in y|Y ) updateHosts ;; esac echoSuccess "Successfully created new Docker environment." } updateHosts () { IP=$(docker-machine ip ${ZEUS_NAME}) echo "${IP} ${ZEUS_DOMAIN}" | sudo tee -a /etc/hosts > /dev/null } dockerStart () { echoPending "Starting machine.." dockerMachineStart echoSuccess "Started machine." dockerEvalEnv dockerUp } dockerStop () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "Machine ${ZEUS_NAME} already off." dockerEvalEnv echoPending "Stopping machine.." [[ $(docker-compose ps -q) ]] && docker-compose down; dockerMachineStop echoSuccess "Stopped machine." } dockerUp () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "Machine $ZEUS_NAME must be running." dockerEvalEnv echoPending "Starting containers.." docker-compose up -d echoSuccess "Started containers." } dockerDown () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "Machine $ZEUS_NAME must be running." dockerEvalEnv echoPending "Stopping containers.." [[ $(docker-compose ps -q) ]] && docker-compose down; echoSuccess "Stopped containers." } dockerInfo () { IP=$(docker-machine ip ${ZEUS_NAME}) STATUS=$(docker-machine status ${ZEUS_NAME}) echo "${GREEN}Virtual machine name: ${YELLOW}${ZEUS_NAME}${RESET}" echo "${GREEN}Domain: ${YELLOW}${ZEUS_DOMAIN}${RESET}" echo "${GREEN}IP Address: ${YELLOW}${IP}${RESET}" echo "${GREEN}Status: ${YELLOW}${STATUS}${RESET}" } dockerList () { dockerEvalEnv docker ps } dockerSsh () { CONTAINER="$1" if [[ "${CONTAINER}" == "" ]]; then CONTAINER=$(echo $ZEUS_DEFAULT_SSH_CONTAINER) fi if [[ "${CONTAINER}" == "" ]]; then echoAbort "You must provide a container name or ID. Run 'list' to identify your containers." fi dockerEvalEnv docker-compose run --rm ${CONTAINER} ${ZEUS_SHELL} } dockerFix () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "The docker-machine must be running." docker-machine regenerate-certs ${ZEUS_NAME} -f docker-machine-nfs ${ZEUS_NAME} -s="$PWD" echoPending "Restarting nfsd -- sudo may be required..." sudo nfsd restart echoSuccess "Successful." dockerStop && dockerStart dockerInfo } dockerTop () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "The docker-machine must be running." docker-machine env "${ZEUS_NAME}" docker stats } dockerEnv () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "The docker-machine must be running." docker-machine env "${ZEUS_NAME}" } dockerCmd () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "The docker-machine must be running." DOCKER_COMPOSE_COMMAND="$1" if [[ -z "$DOCKER_COMPOSE_COMMAND" ]]; then echoAbort "You must specify a docker-compose command." fi CONTAINER="$2" if [[ "$CONTAINER" == "" ]]; then CONTAINER=$(echo $ZEUS_DEFAULT_SSH_CONTAINER) fi if [[ "$CONTAINER" == "" ]]; then echoAbort "You must provide a container name or ID. Run 'list' to identify your containers." fi dockerEvalEnv if ! docker-compose ps --services | grep "$CONTAINER" > /dev/null; then echoAbort "Container $CONTAINER was not found." fi if [[ "$DOCKER_COMPOSE_COMMAND" == *"logs"* ]]; then echoPending "$CONTAINER >: logs" docker-compose ${DOCKER_COMPOSE_COMMAND} ${CONTAINER} return fi COMMAND="$3" if [[ "$COMMAND" == "" ]]; then echoAbort "You must provide a command to run." fi echoPending "$CONTAINER >: $COMMAND" docker-compose ${DOCKER_COMPOSE_COMMAND} ${CONTAINER} ${COMMAND} } dockerRun () { dockerCmd "run --rm" "$1" "$2" } dockerExec () { dockerCmd "exec" "$1" "$2" } dockerLogs () { dockerCmd "logs -f" "$1" } dockerUpdate () { [ -z "$ZEUS_MACHINE_RUNNING" ] && echoAbort "The docker-machine must be running." dockerEvalEnv echoPending "Pulling latest images.." docker-compose pull echoGreen "All images up to date." echoSuccess "Run \`zeus reload\` to recreate the containers with the new images." } [ $# -eq 0 ] && usage [ "$1" == "init" ] && zeusInit [ "$1" == "--version" ] || [ "$1" == "-v" ] && zeusVersion ensureCompatible setPropDefaults case "$1" in create) dockerCreate ;; up|start) dockerStart ;; down) dockerDown ;; stop) dockerStop ;; restart) dockerStop && dockerStart ;; reload) dockerDown && dockerUp ;; update|pull) dockerUpdate ;; info) dockerInfo ;; list) dockerList ;; ssh) dockerSsh "$2" ;; destroy) dockerMachineDestroy ;; fix) dockerFix ;; env) dockerEnv ;; run) container=$2; shift; shift args=$* dockerRun "$container" "$args" ;; exec) container=$2; shift; shift args=$* dockerExec "$container" "$args" ;; logs) dockerLogs "$2" ;; scripts) dockerScripts ;; top) dockerTop ;; *) usage ;; esac