Can't use `--login` because bash profile hasn't been created.
[discourse_docker.git] / launcher
1 #!/bin/bash
2
3 usage () {
4 echo "Usage: launcher COMMAND CONFIG [--skip-prereqs] [--docker-args STRING]"
5 echo "Commands:"
6 echo " start: Start/initialize a container"
7 echo " stop: Stop a running container"
8 echo " restart: Restart a container"
9 echo " destroy: Stop and remove a container"
10 echo " enter: Open a shell to run commands inside the container"
11 echo " logs: View the Docker logs for a container"
12 echo " bootstrap: Bootstrap a container for the config based on a template"
13 echo " run: Run the given command with the config for the given template."
14 echo " rebuild: Rebuild a container (destroy old, bootstrap, start new)"
15 echo " cleanup: Remove all containers that have stopped for > 24 hours"
16 echo
17 echo "Options:"
18 echo " --skip-prereqs Don't check launcher prerequisites"
19 echo " --docker-args Extra arguments to pass when running docker"
20 echo " --skip-mac-address Don't assign a mac address"
21 exit 1
22 }
23
24 command=$1
25 config=$2
26 user_args=""
27
28 if [[ $command == "run" ]]; then
29 run_command=$3
30 fi
31
32 while [ ${#} -gt 0 ]; do
33 case "${1}" in
34 --debug)
35 DEBUG="1"
36 ;;
37 --skip-prereqs)
38 SKIP_PREREQS="1"
39 ;;
40 --skip-mac-address)
41 SKIP_MAC_ADDRESS="1"
42 ;;
43 --docker-args)
44 user_args="$2"
45 shift
46 ;;
47 esac
48
49 shift 1
50 done
51
52 # Docker doesn't like uppercase characters, spaces or special characters, catch it now before we build everything out and then find out
53 re='[[:upper:]/ !@#$%^&*()+~`=]'
54 if [[ $config =~ $re ]];
55 then
56 echo
57 echo "ERROR: Config name '$config' must not contain upper case characters, spaces or special characters. Correct config name and rerun $0."
58 echo
59 exit 1
60 fi
61
62 cd "$(dirname "$0")"
63
64 docker_min_version='17.03.1'
65 docker_rec_version='17.06.2'
66 git_min_version='1.8.0'
67 git_rec_version='1.8.0'
68
69 config_file=containers/"$config".yml
70 cidbootstrap=cids/"$config"_bootstrap.cid
71 local_discourse=local_discourse
72 image=discourse/base:2.0.20180802
73 docker_path=`which docker.io || which docker`
74 git_path=`which git`
75
76 if [ "${SUPERVISED}" = "true" ]; then
77 restart_policy="--restart=no"
78 attach_on_start="-a"
79 attach_on_run="-a stdout -a stderr"
80 else
81 attach_on_run="-d"
82 fi
83
84 if [ -n "$DOCKER_HOST" ]; then
85 docker_ip=`sed -e 's/^tcp:\/\/\(.*\):.*$/\1/' <<< "$DOCKER_HOST"`
86 elif [ -x "$(which ip 2>/dev/null)" ]; then
87 docker_ip=`ip addr show docker0 | \
88 grep 'inet ' | \
89 awk '{ split($2,a,"/"); print a[1] }';`
90 else
91 docker_ip=`ifconfig | \
92 grep -B1 "inet addr" | \
93 awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' | \
94 grep docker0 | \
95 awk -F: '{ print $3 }';`
96 fi
97
98 # From https://stackoverflow.com/a/44660519/702738
99 compare_version() {
100 if [[ $1 == $2 ]]; then
101 return 1
102 fi
103 local IFS=.
104 local i a=(${1%%[^0-9.]*}) b=(${2%%[^0-9.]*})
105 local arem=${1#${1%%[^0-9.]*}} brem=${2#${2%%[^0-9.]*}}
106 for ((i=0; i<${#a[@]} || i<${#b[@]}; i++)); do
107 if ((10#${a[i]:-0} < 10#${b[i]:-0})); then
108 return 1
109 elif ((10#${a[i]:-0} > 10#${b[i]:-0})); then
110 return 0
111 fi
112 done
113 if [ "$arem" '<' "$brem" ]; then
114 return 1
115 elif [ "$arem" '>' "$brem" ]; then
116 return 0
117 fi
118 return 1
119 }
120
121
122 install_docker() {
123 echo "Docker is not installed, you will need to install Docker in order to run Launcher"
124 echo "See https://docs.docker.com/installation/"
125 exit 1
126 }
127
128 check_prereqs() {
129
130 if [ -z $docker_path ]; then
131 install_docker
132 fi
133
134 # 1. docker daemon running?
135 # we send stderr to /dev/null cause we don't care about warnings,
136 # it usually complains about swap which does not matter
137 test=`$docker_path info 2> /dev/null`
138 if [[ $? -ne 0 ]] ; then
139 echo "Cannot connect to the docker daemon - verify it is running and you have access"
140 exit 1
141 fi
142
143 # 2. running an approved storage driver?
144 if ! $docker_path info 2> /dev/null | egrep -q '^Storage Driver: (aufs|btrfs|zfs|overlay|overlay2)$'; then
145 echo "Your Docker installation is not using a supported storage driver. If we were to proceed you may have a broken install."
146 echo "aufs is the recommended storage driver, although zfs/btrfs/overlay and overlay2 may work as well."
147 echo "Other storage drivers are known to be problematic."
148 echo "You can tell what filesystem you are using by running \"docker info\" and looking at the 'Storage Driver' line."
149 echo
150 echo "If you wish to continue anyway using your existing unsupported storage driver,"
151 echo "read the source code of launcher and figure out how to bypass this check."
152 exit 1
153 fi
154
155 # 3. running recommended docker version
156 test=($($docker_path --version)) # Get docker version string
157 test=${test[2]//,/} # Get version alone and strip comma if exists
158
159 # At least minimum docker version
160 if compare_version "${docker_min_version}" "${test}"; then
161 echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
162 exit 1
163 fi
164
165 # Recommend newer docker version
166 if compare_version "${docker_rec_version}" "${test}"; then
167 echo "WARNING: Docker version ${test} deprecated, recommend upgrade to ${docker_rec_version} or newer."
168 fi
169
170 # 4. discourse docker image is downloaded
171 test=`$docker_path images | awk '{print $1 ":" $2 }' | grep "$image"`
172
173 if [ -z "$test" ]; then
174 echo
175 echo "WARNING: We are about to start downloading the Discourse base image"
176 echo "This process may take anywhere between a few minutes to an hour, depending on your network speed"
177 echo
178 echo "Please be patient"
179 echo
180 fi
181
182 # 5. running recommended git version
183 test=($($git_path --version)) # Get git version string
184 test=${test[2]//,/} # Get version alone and strip comma if exists
185
186 # At least minimum version
187 if compare_version "${git_min_version}" "${test}"; then
188 echo "ERROR: Git version ${test} not supported, please upgrade to at least ${git_min_version}, or recommended ${git_rec_version}"
189 exit 1
190 fi
191
192 # Recommend best version
193 if compare_version "${git_rec_version}" "${test}"; then
194 echo "WARNING: Git version ${test} deprecated, recommend upgrade to ${git_rec_version} or newer."
195 fi
196
197 # 6. able to attach stderr / out / tty
198 test=`$docker_path run $user_args -i --rm -a stdout -a stderr $image echo working`
199 if [[ "$test" =~ "working" ]] ; then : ; else
200 echo "Your Docker installation is not working correctly"
201 echo
202 echo "See: https://meta.discourse.org/t/docker-error-on-bootstrap/13657/18?u=sam"
203 exit 1
204 fi
205
206 # 7. enough space for the bootstrap on docker folder
207 folder=`$docker_path info --format '{{.DockerRootDir}}'`
208 safe_folder=${folder:-/var/lib/docker}
209 test=$(($(stat -f --format="%a*%S" $safe_folder)/1024**3 < 5))
210 if [[ $test -ne 0 ]] ; then
211 echo "You have less than 5GB of free space on the disk where $safe_folder is located. You will need more space to continue"
212 df -h $safe_folder
213 echo
214 read -p "Would you like to attempt to recover space by cleaning docker images and containers in the system?(y/N)" -n 1 -r
215 echo
216 if [[ $REPLY =~ ^[Yy]$ ]]
217 then
218 docker system prune
219 echo "If the cleanup was successful, you may try again now"
220 fi
221 exit 1
222 fi
223 }
224
225
226 if [ -z "$SKIP_PREREQS" ] && [ "$command" != "cleanup" ]; then
227 check_prereqs
228 fi
229
230 host_run() {
231 read -r -d '' env_ruby << 'RUBY'
232 require 'yaml'
233
234 input = STDIN.readlines.join
235 yaml = YAML.load(input)
236
237 if host_run = yaml['host_run']
238 params = yaml['params'] || {}
239 host_run.each do |run|
240 params.each do |k,v|
241 run = run.gsub("$#{k}", v)
242 end
243 STDOUT.write "#{run}--SEP--"
244 end
245 end
246 RUBY
247
248 host_run=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
249
250 while [ "$host_run" ] ; do
251 iter=${host_run%%--SEP--*}
252 echo
253 echo "Host run: $iter"
254 $iter || exit 1
255 echo
256 host_run="${host_run#*--SEP--}"
257 done
258 }
259
260
261 set_volumes() {
262 volumes=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
263 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
264 }
265
266 set_links() {
267 links=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
268 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
269 }
270
271 find_templates() {
272 local templates=`cat $1 | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
273 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
274
275 local arrTemplates=${templates// / }
276
277 if [ ! -z "$templates" ]; then
278 for template in "${arrTemplates[@]}"
279 do
280 local nested_templates=$(find_templates $template)
281
282 if [ ! -z "$nested_templates" ]; then
283 templates="$templates $nested_templates"
284 fi
285 done
286
287 echo $templates
288 else
289 echo ""
290 fi
291 }
292
293 set_template_info() {
294 templates=$(find_templates $config_file)
295
296 arrTemplates=(${templates// / })
297 config_data=$(cat $config_file)
298
299 input="hack: true"
300
301 for template in "${arrTemplates[@]}"
302 do
303 [ ! -z $template ] && {
304 input="$input _FILE_SEPERATOR_ $(cat $template)"
305 }
306 done
307
308 # we always want our config file last so it takes priority
309 input="$input _FILE_SEPERATOR_ $config_data"
310
311 read -r -d '' env_ruby << 'RUBY'
312 require 'yaml'
313
314 input=STDIN.readlines.join
315 # default to UTF-8 for the dbs sake
316 env = {'LANG' => 'en_US.UTF-8'}
317 input.split('_FILE_SEPERATOR_').each do |yml|
318 yml.strip!
319 begin
320 env.merge!(YAML.load(yml)['env'] || {})
321 rescue Psych::SyntaxError => e
322 puts e
323 puts "*ERROR."
324 rescue => e
325 puts yml
326 p e
327 end
328 end
329 puts env.map{|k,v| "-e\n#{k}=#{v}" }.join("\n")
330 RUBY
331
332 raw=`exec echo "$input" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
333
334 env=()
335 ok=1
336 while read i; do
337 if [ "$i" == "*ERROR." ]; then
338 ok=0
339 elif [ -n "$i" ]; then
340 env[${#env[@]}]=$i
341 fi
342 done <<< "$raw"
343
344 if [ "$ok" -ne 1 ]; then
345 echo "${env[@]}"
346 echo "YAML syntax error. Please check your containers/*.yml config files."
347 exit 1
348 fi
349
350 read -r -d '' labels_ruby << 'RUBY'
351 require 'yaml'
352
353 input=STDIN.readlines.join
354 # default to UTF-8 for the dbs sake
355 labels = {}
356 input.split('_FILE_SEPERATOR_').each do |yml|
357 yml.strip!
358 begin
359 labels.merge!(YAML.load(yml)['labels'] || {})
360 rescue Psych::SyntaxError => e
361 puts e
362 puts "*ERROR."
363 rescue => e
364 puts yml
365 p e
366 end
367 end
368 puts labels.map{|k,v| "-l\n#{k}=#{v}" }.join("\n")
369 RUBY
370
371 raw=`exec echo "$input" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$labels_ruby"`
372
373 labels=()
374 ok=1
375 while read i; do
376 if [ "$i" == "*ERROR." ]; then
377 ok=0
378 elif [ -n "$i" ]; then
379 labels[${#labels[@]}]=$(echo $i | sed s/{{config}}/${config}/g)
380 fi
381 done <<< "$raw"
382
383 if [ "$ok" -ne 1 ]; then
384 echo "${labels[@]}"
385 echo "YAML syntax error. Please check your containers/*.yml config files."
386 exit 1
387 fi
388 }
389
390 if [ -z $docker_path ]; then
391 install_docker
392 fi
393
394 [ "$command" == "cleanup" ] && {
395 echo
396 echo "The following command will"
397 echo "- Delete all docker images for old containers"
398 echo "- Delete all stopped and orphan containers"
399 echo
400 read -p "Are you sure (Y/n): " -n 1 -r && echo
401 if [[ $REPLY =~ ^[Yy]$ || ! $REPLY ]]
402 then
403 space=$(df /var/lib/docker | awk '{ print $4 }' | grep -v Available)
404 echo "Starting Cleanup (bytes free $space)"
405
406 STATE_DIR=./.gc-state scripts/docker-gc
407
408 rm -f shared/standalone/log/var-log/*.txt
409
410 space=$(df /var/lib/docker | awk '{ print $4 }' | grep -v Available)
411 echo "Finished Cleanup (bytes free $space)"
412
413 else
414 exit 1
415 fi
416
417 if [ -d /var/discourse/shared/standalone/postgres_data_old ]; then
418 echo
419 echo "Old PostgreSQL backup data cluster detected taking up $(du -hs /var/discourse/shared/standalone/postgres_data_old | awk '{print $1}') detected"
420 read -p "Would you like to remove it? (Y/n): " -n 1 -r && echo
421
422 if [[ $REPLY =~ ^[Yy]$ ]]; then
423 echo "removing old PostgreSQL data cluster at /var/discourse/shared/standalone/postgres_data_old..."
424 rm -rf /var/discourse/shared/standalone/postgres_data_old
425 else
426 exit 1
427 fi
428 fi
429
430 exit 0
431 }
432
433 if [ -z "$command" -a -z "$config" ]; then
434 usage
435 fi
436
437 if [ ! "$command" == "setup" ]; then
438 if [[ ! -e $config_file ]]; then
439 echo "Config file was not found, ensure $config_file exists"
440 echo
441 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
442 exit 1
443 fi
444 fi
445
446 docker_version=($($docker_path --version))
447 docker_version=${test[2]//,/}
448 restart_policy=${restart_policy:---restart=always}
449
450 set_existing_container(){
451 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
452 }
453
454 run_stop() {
455
456 set_existing_container
457
458 if [ ! -z $existing ]
459 then
460 (
461 set -x
462 $docker_path stop -t 10 $config
463 )
464 else
465 echo "$config was not started !"
466 exit 1
467 fi
468 }
469
470 set_run_image() {
471 run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
472 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
473
474 if [ -z "$run_image" ]; then
475 run_image="$local_discourse/$config"
476 fi
477 }
478
479 set_boot_command() {
480 boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
481 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
482
483 if [ -z "$boot_command" ]; then
484
485 no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
486 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
487
488 if [ -z "$no_boot_command" ]; then
489 boot_command="/sbin/boot"
490 fi
491 fi
492 }
493
494 run_start() {
495
496 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
497 echo $existing
498 if [ ! -z $existing ]
499 then
500 echo "Nothing to do, your container has already started!"
501 exit 0
502 fi
503
504 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
505 if [ ! -z $existing ]
506 then
507 echo "starting up existing container"
508 (
509 set -x
510 $docker_path start $config
511 )
512 exit 0
513 fi
514
515 host_run
516
517 ports=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
518 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| \"-p #{p}\"}.join(' ')"`
519
520 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
521 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
522
523 set_template_info
524 set_volumes
525 set_links
526 set_run_image
527 set_boot_command
528
529 # get hostname and settings from container configuration
530 for envar in "${env[@]}"
531 do
532 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
533 then
534 # use as environment variable
535 eval $envar
536 fi
537 done
538
539 (
540 hostname=`hostname -s`
541 # overwrite hostname
542 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
543 then
544 hostname=$DISCOURSE_HOSTNAME
545 else
546 hostname=$hostname-$config
547 fi
548
549 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
550 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
551 # docker added more hostname rules
552 hostname=${hostname//_/-}
553
554
555 if [ -z "$SKIP_MAC_ADDRESS" ] ; then
556 mac_address="--mac-address $($docker_path run $user_args -i --rm -a stdout -a stderr $image /bin/sh -c "echo $hostname | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'")"
557 fi
558
559 set -x
560 $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
561 -e DOCKER_HOST_IP="$docker_ip" --name $config -t $ports $volumes $mac_address $docker_args $user_args \
562 $run_image $boot_command
563
564 )
565 exit 0
566
567 }
568
569 setup_bootstrap() {
570 host_run
571
572 # Is the image available?
573 # If not, pull it here so the user is aware what's happening.
574 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
575
576 set_template_info
577
578 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
579 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
580
581 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
582 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
583
584 if [[ ! X"" = X"$base_image" ]]; then
585 image=$base_image
586 fi
587
588 set_volumes
589 set_links
590 }
591
592 run_run() {
593 setup_bootstrap
594
595 $docker_path run --rm --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" -i -a stdin -a stdout -a stderr $volumes $image \
596 /bin/bash -c "$run_command"
597 }
598
599 run_bootstrap() {
600 setup_bootstrap
601 rm -f $cidbootstrap
602
603 run_command="cd /pups &&"
604 if [[ ! "false" = $update_pups ]]; then
605 run_command="$run_command git pull &&"
606 fi
607 run_command="$run_command /pups/bin/pups --stdin"
608
609 echo $run_command
610
611 unset ERR
612 (exec echo "$input" | $docker_path run --shm-size=512m $user_args $links "${env[@]}" -e DOCKER_HOST_IP="$docker_ip" --cidfile $cidbootstrap -i -a stdin -a stdout -a stderr $volumes $image \
613 /bin/bash -c "$run_command") || ERR=$?
614
615 unset FAILED
616 # magic exit code that indicates a retry
617 if [[ "$ERR" == 77 ]]; then
618 $docker_path rm `cat $cidbootstrap`
619 rm $cidbootstrap
620 exit 77
621 elif [[ "$ERR" > 0 ]]; then
622 FAILED=TRUE
623 fi
624
625 if [[ $FAILED = "TRUE" ]]; then
626 if [[ ! -z "$DEBUG" ]]; then
627 $docker_path commit `cat $cidbootstrap` $local_discourse/$config-debug || echo 'FAILED TO COMMIT'
628 echo "** DEBUG ** Maintaining image for diagnostics $local_discourse/$config-debug"
629 fi
630
631 $docker_path rm `cat $cidbootstrap`
632 rm $cidbootstrap
633 echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one"
634 exit 1
635 fi
636
637 sleep 5
638
639 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
640 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
641 }
642
643
644
645 case "$command" in
646 bootstrap)
647 run_bootstrap
648 echo "Successfully bootstrapped, to startup use ./launcher start $config"
649 exit 0
650 ;;
651
652 run)
653 run_run
654 exit 0
655 ;;
656
657 enter)
658 exec $docker_path exec -it $config /bin/bash --login
659 ;;
660
661 stop)
662 run_stop
663 exit 0
664 ;;
665
666 logs)
667
668 $docker_path logs $config
669 exit 0
670 ;;
671
672 restart)
673 run_stop
674 run_start
675 exit 0
676 ;;
677
678 start)
679 run_start
680 exit 0
681 ;;
682
683 rebuild)
684 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
685 echo "Ensuring launcher is up to date"
686
687 git remote update
688
689 LOCAL=$(git rev-parse @)
690 REMOTE=$(git rev-parse @{u})
691 BASE=$(git merge-base @ @{u})
692
693 if [ $LOCAL = $REMOTE ]; then
694 echo "Launcher is up-to-date"
695
696 elif [ $LOCAL = $BASE ]; then
697 echo "Updating Launcher"
698 git pull || (echo 'failed to update' && exit 1)
699
700 for (( i=${#BASH_ARGV[@]}-1,j=0; i>=0,j<${#BASH_ARGV[@]}; i--,j++ ))
701 do
702 args[$j]=${BASH_ARGV[$i]}
703 done
704 exec /bin/bash $0 "${args[@]}" # $@ is empty, because of shift at the beginning. Use BASH_ARGV instead.
705
706 elif [ $REMOTE = $BASE ]; then
707 echo "Your version of Launcher is ahead of origin"
708
709 else
710 echo "Launcher has diverged source, this is only expected in Dev mode"
711 fi
712
713 fi
714
715 set_existing_container
716
717 if [ ! -z $existing ]
718 then
719 echo "Stopping old container"
720 (
721 set -x
722 $docker_path stop -t 10 $config
723 )
724 fi
725
726 run_bootstrap
727
728 if [ ! -z $existing ]
729 then
730 echo "Removing old container"
731 (
732 set -x
733 $docker_path rm $config
734 )
735 fi
736
737 run_start
738 exit 0
739 ;;
740
741
742 destroy)
743 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
744 exit 0
745 ;;
746 esac
747
748 usage