Mercurial > sat_docs
view docker/libervia_cont.sh @ 103:e69883c1ec30
docker (libervia_cont): added a "status" command:
- if libervia container is not running, it exits with error code 1
- if libervia container is running but no server is launched, it exits with error code 2
- if libervia container is running and server is launcher, it exits with error code 0 (success)
server detection is done by doing a simple grep on logs, that's not perfectly reliable (ports can be changed in configuration, even if that doesn't really make sense in Docker context) but should be good enough for this purpose.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 27 Feb 2016 00:45:40 +0100 |
parents | 61ff3bef94a6 |
children | b59491821a8a |
line wrap: on
line source
#!/bin/sh # Libervia container manager # Copyright (C) 2014-2016 Jérôme Poisson (goffi@goffi.org) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. VERSION="0.3.0" APP_NAME="Libervia" ACCOUNT="salutatoi" # environment variables that can be used for configuration: # SAT_CONT_TLS_DIR for TLS certificates directory # SAT_CONT_DOMAIN for the host name # SAT_CONT_BACKUP_DIR is the directory where tar.gz backup will be written # SAT_CONT_DK_EXTRA is used for extra options (used with all containers but sat_data) # SAT_CONT_PORT_<port> is used to specify port when -p is used, <port> must be an exposed port CONTAINERS="prosody sat_pubsub salut sat libervia" TEST_CONT="libervia" # container used to test status DK_DETACH="-d" DK_TERM="-ti" VOLUME_NAME="data" VOLUME_CONT="$ACCOUNT/$VOLUME_NAME" VOLUME_ALIAS="sat_data" DK_VOLUME="--volumes-from $VOLUME_ALIAS" PUBLIC=0 PROSODY_PORTS="5222 5269 5280 5281" PORT_5222_NAME="XMPP client to server" PORT_5269_NAME="XMPP server to server" PORT_5280_NAME="HTTP Upload" PORT_5281_NAME="HTTP Upload (HTTPS)" SAT_PORTS="10143 10125 28915" PORT_10143_NAME="IMAP server" PORT_10125_NAME="SMTP server" PORT_28915_NAME="XMPP file transfer" LIBERVIA_PORTS="8080 8443" PORT_8080_NAME="HTTP" PORT_8443_NAME="HTTPS" NO_PORT="No public port" DOCKER_EXE="docker" USAGE="Usage: $0 [start|stop|restart|status|update|backup|restore|ports|config] [ARGS...]" HELP_SITE="https://wiki.goffi.org/wiki/Docker/en" HELP_MUC="sat@chat.jabberfr.org" CONT_CERT_DIR="/usr/share/sat/certificates" DEFAULT_TMP_DIR="/tmp/tmp_sat_docker" get_dyn_var() { # get dynamicly variable based on given name name=$1 var_type=$2 name_upp=$(echo "$name" | tr '[:lower:]' '[:upper:]') case $var_type in ports) eval echo "\$${name_upp}_PORTS";; port_name) eval echo "\$PORT_${name_upp}_NAME";; esac } list_ports() { # list used ports in currently running containers for cont in $CONTAINERS; do # we get variable name with uppercase container name # some magic to get the ports ports=$(get_dyn_var $cont ports) [ -n "$ports" ] && printf "== $cont ==\n\n" for port in $ports; do # some magic to get port human readable name port_name=$(get_dyn_var $port port_name) real_port=$(docker port $cont $port 2>&1) if [ $? -ne 0 ]; then real_port=$NO_PORT fi # we now show the ports with nice alignment desc="port $port ($port_name):" nb_tabs=$((5-${#desc}/8)) printf "$desc" for i in $(seq $nb_tabs); do printf "\t" done printf "$real_port\n" done [ -n "$ports" ] && printf '\n' done } public_ports_arg() { # create Docker arg to have public ports corresponding to container ports if [ $PUBLIC -ne 1 ]; then return fi cont=$1 ports=$(get_dyn_var $cont ports) ARG="" for port in $ports; do host_port=$(eval echo "\$SAT_CONT_PORT_${port}") if [ -z "$host_port" ]; then host_port=$port fi if [ "$host_port" != 0 ]; then ARG="$ARG -p $host_port:$port" fi done echo $ARG } download_missing() { # download images wich are not present locally for cont in $CONTAINERS $VOLUME_NAME; do image="$ACCOUNT/$cont" docker inspect $image:latest > /dev/null 2>&1 if [ $? -ne 0 ]; then printf "$image is not present locally, downloading it\n" docker pull $image:latest if [ $? -eq 0 ]; then printf "\nDownload of latest $image finished\n\n" else printf "\nError while downloading $image, please check your connection and logs\n" return 1 fi fi done } check_docker() { which $DOCKER_EXE > /dev/null 2>&1 if [ $? -ne 0 ]; then printf "Docker is not installed or not accessible, please install it.\nYou can check $HELP_SITE for instructions\n" return 1 fi } parse_run_args() { # manage arguments for run command while [ $# -gt 0 ]; do case "$1" in -h|--help) cat << OPT_END options available for the run command: -h, --help display this help message -p, --public publish using true ports -d DOMAIN, --domain DOMAIN use DOMAIN as domain name OPT_END exit 0 ;; -d|--domain) shift if [ $# -eq 0 ]; then printf "no domain given, --domain must be followed by a domain\n" exit 1 fi SAT_CONT_DOMAIN="$1" shift ;; -p|--public) shift PUBLIC=1 ;; *) printf "Invalid argument, please check \"$0 run --help\"\n" exit 1 ;; esac done } check_docker || exit 1 if [ $# -ge 1 ];then case $1 in start) CMD=START;; stop) CMD=STOP;; restart) CMD=RESTART;; status) CMD=STATUS;; update) CMD=UPDATE;; backup) CMD=BACKUP;; restore) CMD=RESTORE;; ports) CMD=PORTS;; config) CMD=CONFIG;; -v|--version) printf "$VERSION\n"; exit 0;; -h|--help) printf "$USAGE\n\nYou can check $HELP_SITE for instructions, or go to $HELP_MUC XMPP MUC room for help\n"; exit 0;; *) echo $USAGE exit 1 esac shift else CMD=START fi case $CMD in START) parse_run_args "$@" download_missing || exit 1 printf "Running data container... " # we use -d even if data container doesn't stay in background to get id of the container docker_id=$(docker run -d --name $VOLUME_ALIAS $VOLUME_CONT 2>&1) if [ $? -eq 0 ]; then printf "OK ($docker_id)\n" else echo $docker_id | grep Conflict > /dev/null 2>&1 if [ $? -eq 0 ]; then printf "A data container already exists ($VOLUME_ALIAS), use \"docker ps -a\" to see it\n" else printf "Error, please check data volume\nerror message: $docker_id\n" exit 1 fi fi printf "\nRunning Libervia\n\n" # we first check if we need to mount TLS directory if [ -n "$SAT_CONT_TLS_DIR" ]; then printf "$SAT_CONT_TLS_DIR will be used for TLS certificate\n" DK_TLS="--volume=$SAT_CONT_TLS_DIR:$CONT_CERT_DIR" fi for CONT in $CONTAINERS; do case $CONT in prosody) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME $DK_TLS $(public_ports_arg $CONT) --name prosody" if [ -n "$SAT_CONT_DOMAIN" ]; then OPTS="-e DOMAIN=$SAT_CONT_DOMAIN $OPTS" fi ;; sat_pubsub) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME --name sat_pubsub --link=prosody:prosody";; salut) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME --name salut --link=prosody:prosody";; sat) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME -P $(public_ports_arg $CONT) --name sat --link=prosody:prosody";; libervia) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME --volumes-from sat $DK_TLS -P $(public_ports_arg $CONT) --name libervia --link=sat:sat";; *) printf "Unkown container $CONT\n"; exit 1 esac printf "Launching $CONT... " docker_id=$(docker run $OPTS $SAT_CONT_DK_EXTRA $ACCOUNT/$CONT 2>&1) if [ $? -eq 0 ]; then printf "OK ($docker_id)\n" else printf "Error, please check container or ask help on XMPP MUC sat@chat.jabberfr.org\nerror message: $docker_id\n" printf "Abandon\n" exit 1 fi done printf '\nLibervia is launched and should be reachable in a couple of seconds.\nYou can check logs with "docker logs -f libervia" (or any other container name).\n' printf "An \"admin\" account has been created, you can check its password on $VOLUME_ALIAS container, in file /home/sat/ADMIN_PWD. Config can be tuned on this container.\n" printf 'Below are the ports used to connect, you can go with your browser to Libervia HTTP(S) port.\n\n' list_ports ;; STOP) printf "stopping Libervia\n" REVERSED="" for CONT in $CONTAINERS; do REVERSED="$CONT $REVERSED" done; for CONT in $REVERSED; do printf "\nStopping container $CONT" docker stop $CONT > /dev/null 2>&1 || printf "... Error while stopping $CONT\n" printf "\rDeleting container $CONT" docker rm -v $CONT > /dev/null 2>&1 || printf "... Error while removing $CONT\n" done printf "\n" ;; RESTART) printf "restarting containers...\n" "$0" stop && "$0" start "$@" ;; STATUS) docker inspect $TEST_CONT > /dev/null 2>&1 if [ $? -eq 0 ]; then printf "$APP_NAME is running" # we test the presence of "starting on xxxx" (where xxxx is one of the exposed ports) # this is not really reliable as ports can be changed in configuration # but in most case it should work OK PORTS_REGEX=$(get_dyn_var $TEST_CONT ports | sed 's/ /\\|/') docker logs $TEST_CONT | grep "starting on \($PORTS_REGEX\)" > /dev/null 2>&1 if [ $? -ne 0 ]; then printf " but no server is started\n" exit 2 fi printf "\n" exit 0 else printf "$APP_NAME is not running\n" exit 1 fi ;; UPDATE) printf "updating images...\n" errors=0 for CONT in $CONTAINERS data; do printf "\n*** updating $CONT ***\n" docker pull $ACCOUNT/$CONT:latest if [ $? -ne 0 ]; then printf "\nError while updating $ACCOUNT/$CONT\n" errors=1 fi done if [ $errors -eq 0 ]; then printf "\n\nImages are up-to-date\n" else printf "\n\nSome errors happened while updating images\n" exit 1 fi ;; BACKUP) case $# in 0) SAT_CONT_BACKUP_DIR="$(pwd)";; 1) SAT_CONT_BACKUP_DIR="$1";; *) printf "syntaxe is $0 backup [backup_dir_absolute_path]\n[backup_dir_absolute_path] default to current working dir\n" exit 1 ;; esac SAT_CONT_BACKUP_DIR=$(echo $SAT_CONT_BACKUP_DIR | sed 's%^\/*\|\/*$%\/%g') # we want to be sure that path starts and finishes with "/" filename="sat_data_backup_$(date '+%Y-%m-%d_%H:%M:%S').tar.gz" printf "backing up data container to ${SAT_CONT_BACKUP_DIR}${filename}\n\n" docker run --rm $DK_VOLUME -v "$SAT_CONT_BACKUP_DIR:/backup" debian:jessie tar zcvf "/backup/$filename" -C / -h volumes if [ $? -eq 0 ]; then printf "\nBackup finished and available at ${SAT_CONT_BACKUP_DIR}${filename}\n" else printf "\nBackup Error !\n" exit 1 fi ;; RESTORE) if [ $# -ne 1 ]; then printf "syntaxe is $0 restore <backup_file.tar.gz>\n" exit 1 fi docker run --name $VOLUME_ALIAS $VOLUME_CONT > /dev/null 2>&1 if [ $? -ne 0 ]; then printf "Can't create $VOLUME_ALIAS container.\n\ If you have an existing one, please remove it with \"docker rm -v $VOLUME_ALIAS\" (/!\\ it will remove *ALL* your data)\n\n\ Hint: you can also rename your current data container with \"docker rename $VOLUME_ALIAS new_container_name\"\n" exit 1 fi printf "restoring $1 to $VOLUME_ALIAS container\n\n" HOST_BACKUP_DIR=$(dirname "$1") HOST_BACKUP_NAME=$(basename "$1") if [ $HOST_BACKUP_DIR = "." ]; then # workaround for a Docker bug (container crash if "." is used) HOST_BACKUP_DIR=$(pwd) fi docker run --rm $DK_VOLUME -v "$HOST_BACKUP_DIR:/backup" debian:jessie tar zxvf "/backup/$HOST_BACKUP_NAME" -C / -h volumes if [ $? -eq 0 ]; then printf "\nRestore finished\n" else printf "\nRestore Error !\n" exit 1 fi ;; PORTS) list_ports ;; CONFIG) case $# in 0) CONF="libervia";; 1) CONF="$1";; *) CONF="";; esac case $CONF in libervia) CONT_CONF_FILE="/home/sat/.config/sat/sat.conf" ;; prosody) CONT_CONF_FILE="/etc/prosody/prosody_sat_cfg/prosody.cfg.lua" ;; *) printf "\nPlease enter type of configuration to edit (libervia, prosody)\n" exit 1 ;; esac HOST_CONF_FILE=$(basename $CONT_CONF_FILE) printf "\ngetting configuration for $CONF\n" # we copy config file to a temporary dit # then edit with $EDITOR and put it back TMP_DIR=$(mktemp -d 2>/dev/null) if [ $? -ne 0 ]; then TMP_DIR="$DEFAULT_TMP_DIR" mkdir -p "$TMP_DIR" fi docker cp "$VOLUME_ALIAS:$CONT_CONF_FILE" "$TMP_DIR/$HOST_CONF_FILE" "$EDITOR" "$TMP_DIR/$HOST_CONF_FILE" if [ $? -eq 0 -a -s "$TMP_DIR/$HOST_CONF_FILE" ]; then printf "updating configuration\n" docker cp "$TMP_DIR/$HOST_CONF_FILE" "$VOLUME_ALIAS:$CONT_CONF_FILE" fi rm -rf "$TMP_DIR" ;; *) printf "Error: unknown command !" exit 2 esac