comparison 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
comparison
equal deleted inserted replaced
163:a63f6d360326 164:29873a41aae1
1 #!/bin/sh
2
3 # Libervia container manager
4 # Copyright (C) 2014-2016 Jérôme Poisson (goffi@goffi.org)
5
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
15
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 VERSION="0.3.0"
20 APP_NAME="Libervia"
21 ACCOUNT="salutatoi"
22
23 # environment variables that can be used for configuration:
24 # SAT_CONT_TLS_DIR for TLS certificates directory
25 # SAT_CONT_DOMAIN for the host name
26 # SAT_CONT_BACKUP_DIR is the directory where tar.gz backup will be written
27 # SAT_CONT_DK_EXTRA is used for extra options (used with all containers but sat_data)
28 # SAT_CONT_PORT_<port> is used to specify port when -p is used, <port> must be an exposed port
29
30 CONTAINERS="prosody sat_pubsub salut sat libervia"
31 TEST_CONT="libervia" # container used to test status
32 MAINT_CONT="debian:jessie" # container used for maintenance
33
34 DK_DETACH="-d"
35 DK_TERM="-ti"
36
37 VOLUME_NAME="data"
38 VOLUME_CONT="$ACCOUNT/$VOLUME_NAME"
39 VOLUME_ALIAS="sat_data"
40 DK_VOLUME="--volumes-from $VOLUME_ALIAS"
41
42 PUBLIC=0
43
44 PROSODY_PORTS="5222 5269 5280 5281"
45 PORT_5222_NAME="XMPP client to server"
46 PORT_5269_NAME="XMPP server to server"
47 PORT_5280_NAME="HTTP Upload"
48 PORT_5281_NAME="HTTP Upload (HTTPS)"
49 SAT_PORTS="10143 10125"
50 PORT_10143_NAME="IMAP server"
51 PORT_10125_NAME="SMTP server"
52 LIBERVIA_PORTS="8080 8443"
53 PORT_8080_NAME="HTTP"
54 PORT_8443_NAME="HTTPS"
55 NO_PORT="No public port"
56
57 DOCKER_EXE="docker"
58
59 USAGE="Usage: $0 [start|stop|restart|status|update|backup|restore|ports|config|stats] [ARGS...]"
60
61 HELP_SITE="https://wiki.goffi.org/wiki/Docker/en"
62 HELP_MUC="sat@chat.jabberfr.org"
63
64 CONT_CERT_DIR="/usr/share/sat/certificates"
65 DEFAULT_TMP_DIR="/tmp/tmp_sat_docker"
66
67 eprintf()
68 {
69 >&2 printf "$@"
70 }
71
72 get_dyn_var() {
73 # get dynamicly variable based on given name
74
75 name=$1
76 var_type=$2
77 name_upp=$(echo "$name" | tr '[:lower:]' '[:upper:]')
78 case $var_type in
79 ports) eval echo "\$${name_upp}_PORTS";;
80 port_name) eval echo "\$PORT_${name_upp}_NAME";;
81 esac
82 }
83
84 list_ports() {
85 # list used ports in currently running containers
86
87 for cont in $CONTAINERS; do
88 # we get variable name with uppercase container name
89 # some magic to get the ports
90 ports=$(get_dyn_var $cont ports)
91
92 [ -n "$ports" ] && printf "== $cont ==\n\n"
93
94 for port in $ports; do
95 # some magic to get port human readable name
96 port_name=$(get_dyn_var $port port_name)
97 real_port=$(docker port $cont $port 2>&1)
98 if [ $? -ne 0 ]; then
99 real_port=$NO_PORT
100 fi
101
102 # we now show the ports with nice alignment
103 desc="port $port ($port_name):"
104 nb_tabs=$((5-${#desc}/8))
105 printf "$desc"
106 for i in $(seq $nb_tabs); do
107 printf "\t"
108 done
109 printf "$real_port\n"
110 done
111 [ -n "$ports" ] && printf '\n'
112 done
113 }
114
115 public_ports_arg() {
116 # create Docker arg to have public ports corresponding to container ports
117
118 if [ $PUBLIC -ne 1 ]; then
119 return
120 fi
121 cont=$1
122 ports=$(get_dyn_var $cont ports)
123 ARG=""
124 for port in $ports; do
125 host_port=$(eval echo "\$SAT_CONT_PORT_${port}")
126 if [ -z "$host_port" ]; then
127 host_port=$port
128 fi
129 if [ "$host_port" != 0 ]; then
130 ARG="$ARG -p $host_port:$port"
131 fi
132 done
133 echo $ARG
134 }
135
136 download_missing() {
137 # download images wich are not present locally
138 for cont in $CONTAINERS $VOLUME_NAME; do
139 image="$ACCOUNT/$cont"
140 docker inspect $image:latest > /dev/null 2>&1
141 if [ $? -ne 0 ]; then
142 printf "$image is not present locally, downloading it\n"
143 docker pull $image:latest
144 if [ $? -eq 0 ]; then
145 printf "\nDownload of latest $image finished\n\n"
146 else
147 eprintf "\nError while downloading $image, please check your connection and logs\n"
148 return 1
149 fi
150 fi
151 done
152 }
153
154 check_docker() {
155 which $DOCKER_EXE > /dev/null 2>&1
156 if [ $? -ne 0 ]; then
157 printf "Docker is not installed or not accessible, please install it.\nYou can check $HELP_SITE for instructions\n"
158 return 1
159 fi
160 }
161
162 check_docker_version() {
163 # check if current docker version is greater than or equal to the requested one
164 wanted_major=$1
165 wanted_minor=$2
166 wanted_rev=$3
167 raw=$(docker --version | grep -o '\([0-9]\+\)\.[0-9]\+\.[0-9]\+')
168 docker_major=$(echo "$raw" | cut -d . -f 1)
169 docker_minor=$(echo "$raw" | cut -d . -f 2)
170 docker_rev=$(echo "$raw" | cut -d . -f 3)
171 for name in major minor rev; do
172 docker_val=$(eval echo \$docker_$name)
173 wanted_val=$(eval echo \$wanted_$name)
174 if [ $docker_val -gt $wanted_val ]; then
175 return 0
176 fi
177 if [ $docker_val -lt $wanted_val ]; then
178 return 1
179 fi
180 done
181
182 # wanted version and docker version are the same
183 return 0
184 }
185
186 parse_run_args() {
187 # manage arguments for run command
188
189 while [ $# -gt 0 ]; do
190 case "$1" in
191
192 -h|--help)
193 cat << OPT_END
194 options available for the run command:
195
196 -h, --help display this help message
197 -p, --public publish using true ports
198 -d DOMAIN, --domain DOMAIN use DOMAIN as domain name
199 OPT_END
200 exit 0
201 ;;
202
203 -d|--domain)
204 shift
205 if [ $# -eq 0 ]; then
206 printf "no domain given, --domain must be followed by a domain\n"
207 exit 1
208 fi
209 SAT_CONT_DOMAIN="$1"
210 shift
211 ;;
212
213 -p|--public)
214 shift
215 PUBLIC=1
216 ;;
217
218 *) printf "Invalid argument, please check \"$0 run --help\"\n"
219 exit 1
220 ;;
221 esac
222 done
223 }
224
225 check_docker || exit 1
226
227 if [ $# -ge 1 ];then
228 case $1 in
229 start) CMD=START;;
230 stop) CMD=STOP;;
231 restart) CMD=RESTART;;
232 status) CMD=STATUS;;
233 update) CMD=UPDATE;;
234 backup) CMD=BACKUP;;
235 restore) CMD=RESTORE;;
236 ports) CMD=PORTS;;
237 config) CMD=CONFIG;;
238 stats) CMD=STATS;;
239 -v|--version) printf "$VERSION\n"; exit 0;;
240 -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;;
241 *) echo $USAGE
242 exit 1
243 esac
244 shift
245 else
246 CMD=START
247 fi
248
249 case $CMD in
250 START)
251 parse_run_args "$@"
252 download_missing || exit 1
253
254 printf "Running data container... "
255 # we use -d even if data container doesn't stay in background to get id of the container
256 docker_id=$(docker run -d --name $VOLUME_ALIAS $VOLUME_CONT 2>&1)
257 if [ $? -eq 0 ]; then
258 printf "OK ($docker_id)\n"
259 else
260 echo $docker_id | grep Conflict > /dev/null 2>&1
261 if [ $? -eq 0 ]; then
262 printf "A data container already exists ($VOLUME_ALIAS), use \"docker ps -a\" to see it\n"
263 else
264 eprintf "Error, please check data volume\nerror message: $docker_id\n"
265 exit 1
266 fi
267 fi
268 printf "\nRunning Libervia\n\n"
269 # we first check if we need to mount TLS directory
270 if [ -n "$SAT_CONT_TLS_DIR" ]; then
271 printf "$SAT_CONT_TLS_DIR will be used for TLS certificate\n"
272 DK_TLS="--volume=$SAT_CONT_TLS_DIR:$CONT_CERT_DIR"
273 fi
274 for CONT in $CONTAINERS; do
275 case $CONT in
276 prosody) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME $DK_TLS $(public_ports_arg $CONT) --name prosody"
277 if [ -n "$SAT_CONT_DOMAIN" ]; then
278 OPTS="-e DOMAIN=$SAT_CONT_DOMAIN $OPTS"
279 fi
280 ;;
281 sat_pubsub) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME --name sat_pubsub --link=prosody:prosody";;
282 salut) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME --name salut --link=prosody:prosody";;
283 sat) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME -P $(public_ports_arg $CONT) --name sat --link=prosody:prosody";;
284 libervia) OPTS="$DK_DETACH $DK_TERM $DK_VOLUME --volumes-from sat $DK_TLS -P $(public_ports_arg $CONT) --name libervia --link=sat:sat";;
285 *) eprintf "Unkown container $CONT\n"; exit 1
286 esac
287 printf "Launching $CONT... "
288 docker_id=$(docker run $OPTS $SAT_CONT_DK_EXTRA $ACCOUNT/$CONT 2>&1)
289 if [ $? -eq 0 ]; then
290 printf "OK ($docker_id)\n"
291 else
292 eprintf "Error, please check container or ask help on XMPP MUC sat@chat.jabberfr.org\nerror message: $docker_id\n"
293 eprintf "Abandon\n"
294 exit 1
295 fi
296 done
297 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'
298 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"
299 printf 'Below are the ports used to connect, you can go with your browser to Libervia HTTP(S) port.\n\n'
300 list_ports
301 ;;
302 STOP)
303 printf "stopping Libervia\n"
304 REVERSED=""
305 for CONT in $CONTAINERS; do
306 REVERSED="$CONT $REVERSED"
307 done;
308 for CONT in $REVERSED; do
309 printf "\nStopping container $CONT"
310 docker stop $CONT > /dev/null 2>&1 || eprintf "... Error while stopping $CONT\n"
311 printf "\rDeleting container $CONT"
312 docker rm -v $CONT > /dev/null 2>&1 || eprintf "... Error while removing $CONT\n"
313 done
314 printf "\n"
315 ;;
316 RESTART)
317 printf "restarting containers...\n"
318 "$0" stop && "$0" start "$@"
319 ;;
320 STATUS)
321 docker inspect $TEST_CONT > /dev/null 2>&1
322 if [ $? -eq 0 ]; then
323 printf "$APP_NAME is running"
324 # we test the presence of "starting on xxxx" (where xxxx is one of the exposed ports)
325 # this is not really reliable as ports can be changed in configuration
326 # but in most case it should work OK
327 PORTS_REGEX=$(get_dyn_var $TEST_CONT ports | sed 's/ /\\|/')
328 docker logs $TEST_CONT | grep "starting on \($PORTS_REGEX\)" > /dev/null 2>&1
329 if [ $? -ne 0 ]; then
330 printf " but no server is started\n"
331 exit 2
332 fi
333 printf "\n"
334 exit 0
335 else
336 printf "$APP_NAME is not running\n"
337 exit 1
338 fi
339 ;;
340 UPDATE)
341 printf "updating images...\n"
342 errors=0
343 for CONT in $CONTAINERS data; do
344 printf "\n*** updating $CONT ***\n"
345 docker pull $ACCOUNT/$CONT:latest
346 if [ $? -ne 0 ]; then
347 eprintf "\nError while updating $ACCOUNT/$CONT\n"
348 errors=1
349 fi
350 done
351 if [ $errors -eq 0 ]; then
352 printf "\n\nImages are up-to-date\n"
353 else
354 eprintf "\n\nSome errors happened while updating images\n"
355 exit 1
356 fi
357 ;;
358 BACKUP)
359 case $# in
360 0) SAT_CONT_BACKUP_DIR="$(pwd)";;
361 1) SAT_CONT_BACKUP_DIR="$1";;
362 *) printf "syntaxe is $0 backup [backup_dir_absolute_path]\n[backup_dir_absolute_path] default to current working dir\n"
363 exit 1
364 ;;
365 esac
366 SAT_CONT_BACKUP_DIR=$(echo $SAT_CONT_BACKUP_DIR | sed 's%^\/*\|\/*$%\/%g') # we want to be sure that path starts and finishes with "/"
367 filename="sat_data_backup_$(date '+%Y-%m-%d_%H:%M:%S').tar.gz"
368 printf "backing up data container to ${SAT_CONT_BACKUP_DIR}${filename}\n\n"
369 docker run --rm $DK_VOLUME -v "$SAT_CONT_BACKUP_DIR:/backup" $MAINT_CONT tar zcvf "/backup/$filename" -C / -h volumes
370 if [ $? -eq 0 ]; then
371 printf "\nBackup finished and available at ${SAT_CONT_BACKUP_DIR}${filename}\n"
372 else
373 eprintf "\nBackup Error !\n"
374 exit 1
375 fi
376 ;;
377 RESTORE)
378 if [ $# -ne 1 ]; then
379 printf "syntaxe is $0 restore <backup_file.tar.gz>\n"
380 exit 1
381 fi
382 docker run --name $VOLUME_ALIAS $VOLUME_CONT > /dev/null 2>&1
383 if [ $? -ne 0 ]; then
384 eprintf "Can't create $VOLUME_ALIAS container.\n\
385 If you have an existing one, please remove it with \"docker rm -v $VOLUME_ALIAS\" (/!\\ it will remove *ALL* your data)\n\n\
386 Hint: you can also rename your current data container with \"docker rename $VOLUME_ALIAS new_container_name\"\n"
387 exit 1
388 fi
389
390 printf "restoring $1 to $VOLUME_ALIAS container\n\n"
391 HOST_BACKUP_DIR=$(dirname "$1")
392 HOST_BACKUP_NAME=$(basename "$1")
393 if [ $HOST_BACKUP_DIR = "." ]; then
394 # workaround for a Docker bug (container crash if "." is used)
395 HOST_BACKUP_DIR=$(pwd)
396 fi
397 docker run --rm $DK_VOLUME -v "$HOST_BACKUP_DIR:/backup" $MAINT_CONT tar zxvf "/backup/$HOST_BACKUP_NAME" -C / -h volumes
398 if [ $? -eq 0 ]; then
399 printf "\nRestore finished\n"
400 else
401 eprintf "\nRestore Error !\n"
402 exit 1
403 fi
404 ;;
405 PORTS)
406 list_ports
407 ;;
408 CONFIG)
409 case $# in
410 0) CONF="libervia";;
411 1) CONF="$1";;
412 *) CONF="";;
413 esac
414 case $CONF in
415 libervia)
416 CONT_CONF_FILE="/home/sat/.config/sat/sat.conf"
417 ;;
418 prosody)
419 CONT_CONF_FILE="/etc/prosody/prosody_sat_cfg/prosody.cfg.lua"
420 ;;
421 *) printf "\nPlease enter type of configuration to edit (libervia, prosody)\n"
422 exit 1
423 ;;
424 esac
425
426 HOST_CONF_FILE=$(basename $CONT_CONF_FILE)
427
428 printf "\ngetting configuration for $CONF\n"
429 # we copy config file to a temporary dit
430 # then edit with $EDITOR and put it back
431
432 TMP_DIR=$(mktemp -d 2>/dev/null)
433 if [ $? -ne 0 ]; then
434 TMP_DIR="$DEFAULT_TMP_DIR"
435 mkdir -p "$TMP_DIR"
436 fi
437
438 docker cp "$VOLUME_ALIAS:$CONT_CONF_FILE" "$TMP_DIR/"
439 "$EDITOR" "$TMP_DIR/$HOST_CONF_FILE"
440 if [ $? -eq 0 -a -s "$TMP_DIR/$HOST_CONF_FILE" ]; then
441 printf "updating configuration\n"
442 check_docker_version 1 8 0
443 if [ $? -eq 0 ]; then
444 docker cp "$TMP_DIR/$HOST_CONF_FILE" "$VOLUME_ALIAS:$CONT_CONF_FILE"
445 else
446 eprintf "Old Docker version detected, using workaround, please update!\n"
447 docker run --rm $DK_VOLUME -v "$TMP_DIR:/tmp_config" $MAINT_CONT /bin/cp -f "/tmp_config/$HOST_CONF_FILE" "$CONT_CONF_FILE"
448 fi
449 # "docker cp" copy file on container as root, if an option is available later to change this behaviour,
450 # the following operation could be removed
451 printf "ownership fix..."
452 docker run --rm $DK_VOLUME $MAINT_CONT /bin/chown 1000:1000 "$CONT_CONF_FILE"
453 printf "done\n"
454 fi
455 rm -rf "$TMP_DIR"
456 ;;
457 STATS)
458 if [ -n "$1" -a "$1" != "--no-stream" ]; then
459 printf "usage: $0 stats [--no-stream]\n"
460 exit 1
461 fi
462 docker stats $1 $CONTAINERS
463 ;;
464 *) eprintf "Error: unknown command !"
465 exit 2
466 esac