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