Merge pull request #239 from pfaffman/add_memconfig
[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.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 "Recommend setting for db_shared_buffers: ${db_shared_buffers}GB"
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 "db_shared_buffers set successfully."
464 rm $changelog
465 else if grep "^ db_shared_buffers:" $config_file
466 then
467 echo "db_shared_buffers already set. Unchanged."
468 else
469 echo -e ". . . oops!\n---> db_shared_buffers not found in $config_file."
470 fi
471 fi
472
473 # set UNICORN_WORKERS: 2*GB or 2*cores (the same on DO)
474 if [ "$avail_gb" -le "2" ]
475 then
476 unicorn_workers=`expr $avail_gb \* 2`
477 else
478 unicorn_workers=`expr $avail_cores \* 2`
479 fi
480
481 echo -e "Recommended setting UNICORN_WORKERS: $unicorn_workers"
482 sed -i -e "s/^ #UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
483 if [ -s $changelog ]
484 then
485 echo "UNICORN_WORKERS set successfully."
486 rm $changelog
487 else if grep "^ UNICORN_WORKERS:" $config_file
488 then
489 echo "UNICORN_WORKERS already set. Unchanged."
490 else
491 echo -e ". . . oops!\n---> UNICORN_WORKERS not found in $config_file.\n"
492 fi
493 fi
494 }
495
496 run_start() {
497
498 existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
499 echo $existing
500 if [ ! -z $existing ]
501 then
502 echo "Nothing to do, your container has already started!"
503 exit 1
504 fi
505
506 existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
507 if [ ! -z $existing ]
508 then
509 echo "starting up existing container"
510 (
511 set -x
512 $docker_path start $config
513 )
514 exit 0
515 fi
516
517 host_run
518 ports=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
519 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| \"-p #{p}\"}.join(' ')"`
520
521 IFS='-p ' read -a array <<< "$ports"
522 for element in "${array[@]}"
523 do
524 IFS=':' read -a args <<< "$element"
525 if [ "${#args[@]}" == "2" ]; then
526 check_ports "${args[0]}"
527 elif [ "${#args[@]}" == "3" ]; then
528 check_ports "${args[1]}"
529 fi
530 done
531
532 docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
533 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
534
535 set_template_info
536 set_volumes
537 set_links
538 set_run_image
539 set_boot_command
540
541 # get hostname and settings from container configuration
542 for envar in "${env[@]}"
543 do
544 if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
545 then
546 # use as environment variable
547 eval $envar
548 fi
549 done
550
551 (
552 hostname=`hostname -s`
553 # overwrite hostname
554 if [ "$DOCKER_USE_HOSTNAME" = "true" ]
555 then
556 hostname=$DISCOURSE_HOSTNAME
557 else
558 hostname=$hostname-$config
559 fi
560
561 # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
562 # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
563 # docker added more hostname rules
564 hostname=${hostname/_/-}
565
566 set -x
567 $docker_path run $user_args $links $attach_on_run $restart_policy "${env[@]}" -h "$hostname" \
568 -e DOCKER_HOST_IP=$docker_ip --name $config -t $ports $volumes $docker_args $run_image $boot_command
569
570 )
571 exit 0
572
573 }
574
575 valid_config_check() {
576
577 valid_config="y"
578 for x in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
579 DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
580 do
581 mail_var=`grep "^ $x:" $config_file`
582 result=$?
583 if (( result == 0 ))
584 then
585 if [[ $mail_var = *"example.com"* ]]
586 then
587 echo "Warning: $x left at incorrect default of example.com"
588 valid_config="n"
589 fi
590 else
591 echo "Warning: $x not configured."
592 valid_config="n"
593 fi
594 done
595 if [ -t 0 ] && [ "$valid_config" != "y" ]; then
596 echo
597 read -p "Press ENTER to continue, or Ctrl-C to exit and edit $config_file."
598 fi
599 }
600
601 run_bootstrap() {
602
603 # Does your system meet the minimum requirements?
604 if [ "$opt" != "--skip-prereqs" ] ; then
605 check_resources
606 fi
607
608 # is our configuration file valid?
609 valid_config_check
610
611 host_run
612
613 # Is the image available?
614 # If not, pull it here so the user is aware what's happening.
615 $docker_path history $image >/dev/null 2>&1 || $docker_path pull $image
616
617 set_template_info
618
619 base_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
620 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
621
622 update_pups=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
623 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
624
625 if [[ ! X"" = X"$base_image" ]]; then
626 image=$base_image
627 fi
628
629 set_volumes
630 set_links
631
632 rm -f $cidbootstrap
633
634 run_command="cd /pups &&"
635 if [[ ! "false" = $update_pups ]]; then
636 run_command="$run_command git pull &&"
637 fi
638 run_command="$run_command /pups/bin/pups --stdin"
639
640 echo $run_command
641
642 (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 \
643 /bin/bash -c "$run_command") \
644 || ($docker_path rm `cat $cidbootstrap` && rm $cidbootstrap)
645
646 [ ! -e $cidbootstrap ] && echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one" && exit 1
647
648 sleep 5
649
650 $docker_path commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
651 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
652 }
653
654
655
656 case "$command" in
657 bootstrap)
658 run_bootstrap
659 echo "Successfully bootstrapped, to startup use ./launcher start $config"
660 exit 0
661 ;;
662
663 enter)
664 exec $docker_path exec -it $config /bin/bash --login
665 ;;
666
667 stop)
668 run_stop
669 exit 0
670 ;;
671
672 logs)
673
674 $docker_path logs $config
675 exit 0
676 ;;
677
678 restart)
679 run_stop
680 run_start
681 exit 0
682 ;;
683
684 start)
685 run_start
686 exit 0
687 ;;
688
689 memconfig)
690 run_memconfig
691 exit 0
692 ;;
693
694 rebuild)
695 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
696 echo "Ensuring discourse docker is up to date"
697
698 git remote update
699
700 LOCAL=$(git rev-parse @)
701 REMOTE=$(git rev-parse @{u})
702 BASE=$(git merge-base @ @{u})
703
704 if [ $LOCAL = $REMOTE ]; then
705 echo "Discourse Docker is up-to-date"
706
707 elif [ $LOCAL = $BASE ]; then
708 echo "Updating Discourse Docker"
709 git pull || (echo 'failed to update' && exit 1)
710 exec /bin/bash $0 $@
711
712 elif [ $REMOTE = $BASE ]; then
713 echo "Your version of Discourse Docker is ahead of origin"
714
715 else
716 echo "Discourse Docker has diverged source, this is only expected in Dev mode"
717 fi
718
719 fi
720
721 set_existing_container
722
723 if [ ! -z $existing ]
724 then
725 echo "Stopping old container"
726 (
727 set -x
728 $docker_path stop -t 10 $config
729 )
730 fi
731
732 run_bootstrap
733
734 if [ ! -z $existing ]
735 then
736 echo "Removing old container"
737 (
738 set -x
739 $docker_path rm $config
740 )
741 fi
742
743 run_start
744 exit 0
745 ;;
746
747
748 destroy)
749 (set -x; $docker_path stop -t 10 $config && $docker_path rm $config) || (echo "$config was not found" && exit 0)
750 exit 0
751 ;;
752 esac
753
754 usage