diff docker_legacy/libervia_cont.sh @ 164:29873a41aae1

docker: new docker files are now in sat main repos, this one is legacy
author Goffi <goffi@goffi.org>
date Fri, 01 Jan 2021 18:33:52 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docker_legacy/libervia_cont.sh	Fri Jan 01 18:33:52 2021 +0100
@@ -0,0 +1,466 @@
+#!/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
+MAINT_CONT="debian:jessie" # container used for maintenance
+
+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"
+PORT_10143_NAME="IMAP server"
+PORT_10125_NAME="SMTP server"
+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|stats] [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"
+
+eprintf()
+{
+   >&2 printf "$@"
+}
+
+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
+                eprintf "\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
+}
+
+check_docker_version() {
+    # check if current docker version is greater than or equal to the requested one
+    wanted_major=$1
+    wanted_minor=$2
+    wanted_rev=$3
+    raw=$(docker --version | grep -o '\([0-9]\+\)\.[0-9]\+\.[0-9]\+')
+    docker_major=$(echo "$raw" |  cut -d . -f 1)
+    docker_minor=$(echo "$raw" |  cut -d . -f 2)
+    docker_rev=$(echo "$raw" |  cut -d . -f 3)
+    for name in major minor rev; do
+        docker_val=$(eval echo \$docker_$name)
+        wanted_val=$(eval echo \$wanted_$name)
+        if [ $docker_val -gt $wanted_val ]; then
+            return 0
+        fi
+        if [ $docker_val -lt $wanted_val ]; then
+            return 1
+        fi
+    done
+
+    # wanted version and docker version are the same
+    return 0
+}
+
+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;;
+        stats) CMD=STATS;;
+        -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
+                eprintf "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";;
+                *) eprintf "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
+                eprintf "Error, please check container or ask help on XMPP MUC sat@chat.jabberfr.org\nerror message: $docker_id\n"
+                eprintf "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  || eprintf "... Error while stopping $CONT\n"
+            printf "\rDeleting container $CONT"
+            docker rm -v $CONT > /dev/null 2>&1 || eprintf "... 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
+                eprintf "\nError while updating $ACCOUNT/$CONT\n"
+                errors=1
+            fi
+        done
+        if [ $errors -eq 0 ]; then
+            printf "\n\nImages are up-to-date\n"
+        else
+            eprintf "\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" $MAINT_CONT tar zcvf "/backup/$filename" -C / -h volumes
+        if [ $? -eq 0 ]; then
+            printf "\nBackup finished and available at ${SAT_CONT_BACKUP_DIR}${filename}\n"
+        else
+            eprintf "\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
+            eprintf "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" $MAINT_CONT tar zxvf "/backup/$HOST_BACKUP_NAME" -C / -h volumes
+        if [ $? -eq 0 ]; then
+            printf "\nRestore finished\n"
+        else
+            eprintf "\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/"
+        "$EDITOR" "$TMP_DIR/$HOST_CONF_FILE"
+        if [ $? -eq 0 -a -s "$TMP_DIR/$HOST_CONF_FILE" ]; then
+            printf "updating configuration\n"
+            check_docker_version 1 8 0
+            if [ $? -eq 0 ]; then
+                docker cp "$TMP_DIR/$HOST_CONF_FILE" "$VOLUME_ALIAS:$CONT_CONF_FILE"
+            else
+                eprintf "Old Docker version detected, using workaround, please update!\n"
+                docker run --rm $DK_VOLUME -v "$TMP_DIR:/tmp_config" $MAINT_CONT /bin/cp -f "/tmp_config/$HOST_CONF_FILE" "$CONT_CONF_FILE"
+            fi
+            # "docker cp" copy file on container as root, if an option is available later to change this behaviour,
+            # the following operation could be removed
+            printf "ownership fix..."
+            docker run --rm $DK_VOLUME $MAINT_CONT /bin/chown 1000:1000 "$CONT_CONF_FILE"
+            printf "done\n"
+        fi
+        rm -rf "$TMP_DIR"
+        ;;
+    STATS)
+        if [ -n "$1" -a "$1" != "--no-stream" ]; then
+            printf "usage: $0 stats [--no-stream]\n"
+            exit 1
+        fi
+        docker stats $1 $CONTAINERS
+        ;;
+    *) eprintf "Error: unknown command !"
+       exit 2
+esac