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