9 docker_min_version
='1.2.0'
10 docker_rec_version
='1.2.0'
12 config_file
=containers
/"$config".yml
13 cidfile
=cids
/"$config".cid
14 cidbootstrap
=cids
/"$config"_boostrap.cid
15 local_discourse
=local_discourse
16 image
=samsaffron
/discourse
:1.0.5
17 docker_path
=`which docker.io || which docker`
19 if [ "${SUPERVISED}" = "true" ]; then
20 restart_policy
="--restart=no"
22 attach_on_run
="-a stdout -a stderr"
27 if [ -x "$(which ip 2>/dev/null)" ]; then
28 docker_ip
=`ip addr show docker0 | \
30 awk '{ split($2,a,"/"); print a[1] }';`
32 docker_ip
=`ifconfig | \
33 grep -B1 "inet addr" | \
34 awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' | \
36 awk -F: '{ print $3 }';`
41 echo "Usage: launcher COMMAND CONFIG [--skip-prereqs]"
43 echo " start: Start/initialize a container"
44 echo " stop: Stop a running container"
45 echo " restart: Restart a container"
46 echo " destroy: Stop and remove a container"
47 echo " enter: Use nsenter to enter a container"
48 echo " ssh: Start a bash shell in a running container"
49 echo " logs: Docker logs for container"
50 echo " mailtest: Test the mail settings in a container"
51 echo " bootstrap: Bootstrap a container for the config based on a template"
52 echo " rebuild: Rebuild a container (destroy old, bootstrap, start new)"
55 echo " --skip-prereqs Don't check prerequisites"
62 IFS
=.
read -a ver_a
<<< "$1"
63 IFS
=.
read -a ver_b
<<< "$2"
65 while [[ -n $ver_a ]]; do
66 if (( ver_a
> ver_b
)); then
68 elif (( ver_b
> ver_a
)); then
77 return 1 # They are equal
82 # 1. docker daemon running?
83 test=`$docker_path info >/dev/null`
85 if [[ $?
-ne 0 ]] ; then
86 echo "Cannot connect to the docker daemon - verify it is running and you have access"
90 # 2. running aufs or btrfs
91 test=`$docker_path info 2> /dev/null | grep 'Driver: '`
92 if [[ "$test" =~
[aufs|btrfs
] ]] ; then : ; else
93 echo "Your Docker installation is not using the recommended AuFS (union filesystem) and may be unstable."
94 echo "If you are unable to bootstrap / stop your image please report the issue at:"
95 echo "https://meta.discourse.org/t/discourse-docker-installation-without-aufs/15639"
98 # 3. running recommended docker version
99 test=($
($docker_path --version)) # Get docker version string
100 test=${test[2]//,/} # Get version alone and strip comma if exists
102 [[ "$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
104 # At least minimum version
105 if compare_version
"${docker_min_version}" "${test}"; then
106 echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
110 # Recommend best version
111 if compare_version
"${docker_rec_version}" "${test}"; then
112 echo "WARNING: Docker version ${test} deprecated, recommend upgrade to ${docker_rec_version} or newer."
115 # 4. able to attach stderr / out / tty
116 test=`$docker_path run -i --rm -a stdout -a stderr $image echo working`
117 if [[ "$test" =~
"working" ]] ; then : ; else
118 echo "Your Docker installation is not working correctly"
120 echo "See: https://meta.discourse.org/t/docker-error-on-bootstrap/13657/18?u=sam"
125 if [ "$opt" != "--skip-prereqs" ] ; then
130 local ${ssh_key_locations}
137 for keyfile
in "${ssh_key_locations[@]}"; do
138 if [[ -e ${keyfile} ]] ; then
139 ssh_pub_key
="$(cat ${keyfile})"
145 echo "This user has no SSH key, but a SSH key is required to access the Discourse Docker container."
146 read -p "Generate a SSH key? (Y/n) " -n 1 -r
147 if [[ $REPLY =~ ^
[Nn
]$
]] ; then
149 echo WARNING
: You may not be able to log
in to your container.
153 echo Generating SSH key
154 mkdir
-p ~
/.
ssh && ssh-keygen
-f ~
/.ssh
/id_rsa
-t rsa
-N ''
156 ssh_pub_key
="$(cat ~/.ssh/id_rsa.pub)"
167 echo "Docker is not installed, make sure you are running on the 3.8 kernel"
168 echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
170 echo "sudo apt-get update"
171 echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
175 echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
176 echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
177 echo "sudo apt-get update"
178 echo "sudo apt-get install lxc-docker"
184 read -r -d '' env_ruby
<< 'RUBY'
187 input
= STDIN.readlines.
join
188 yaml
= YAML.load
(input
)
190 if host_run
= yaml
['host_run']
191 params
= yaml
['params'] ||
{}
192 host_run.each
do |run|
194 run
= run.gsub
("$#{k}", v
)
196 STDOUT.
write "#{run}--SEP--"
201 host_run
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
203 while [ "$host_run" ] ; do
204 iter
=${host_run%%--SEP--*}
206 echo "Host run: $iter"
209 host_run
="${host_run#*--SEP--}"
215 volumes
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
216 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
220 links
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
221 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
224 set_template_info
() {
226 templates
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
227 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
230 arrTemplates
=(${templates// / })
231 config_data
=$
(cat $config_file)
236 for template
in "${arrTemplates[@]}"
238 [ ! -z $template ] && {
239 input
="$input _FILE_SEPERATOR_ $(cat $template)"
243 # we always want our config file last so it takes priority
244 input
="$input _FILE_SEPERATOR_ $config_data"
246 read -r -d '' env_ruby
<< 'RUBY'
249 input
=STDIN.readlines.
join
250 # default to UTF-8 for the dbs sake
251 env
= {'LANG' => 'en_US.UTF-8'}
252 input.
split('_FILE_SEPERATOR_').each
do |yml|
255 env.merge
!(YAML.load
(yml
)['env'] ||
{})
256 rescue Psych
::SyntaxError
=> e
264 puts env.map
{|k
,v|
"-e\n#{k}=#{v}" }.
join("\n")
267 raw
=`exec echo "$input" | $docker_path run --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
272 if [ "$i" == "*ERROR." ]; then
274 elif [ -n "$i" ]; then
279 if [ "$ok" -ne 1 ]; then
281 echo "YAML syntax error. Please check your /var/docker/containers/*.yml config files."
284 echo "Calculated ENV: ${env[@]}"
287 [ -z $docker_path ] && {
296 if [ ! -e $config_file ]
298 echo "Config file was not found, ensure $config_file exists"
300 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
305 docker_version
=($
($docker_path --version))
306 docker_version
=${test[2]//,/}
308 if compare_version
"1.2.0" "$docker_version"; then
309 echo "We recommend you upgrade docker, the version you are running has no restart policies, on reboot your container may not start up"
312 restart_policy
=${restart_policy:---restart=always}
317 if [ ! -e $config_file ]; then
318 echo "Config does not exist: $config_file" >&2
321 exec scripts
/mailtest
$config_file
330 $docker_path stop
-t 10 `cat $cidfile`
340 echo "No cid found, creating a new container"
341 ports
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
342 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
348 existing
=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
349 if [ ! -z $existing ]
351 echo "Found an existing container by its name, recovering cidfile, please rerun"
352 echo $existing > $cidfile
356 $docker_path run
$links $attach_on_run $restart_policy "${env[@]}" -h "`hostname`-$config" -e DOCKER_HOST_IP
=$docker_ip --name $config -t --cidfile $cidfile $ports \
357 $volumes $local_discourse/$config /sbin
/boot
365 echo "Detected empty cid file, deleting, please re-run"
370 found
=`$docker_path ps -q -a --no-trunc | grep $cid`
373 echo "Invalid cid file, deleting, please re-run"
378 echo "cid found, ensuring container is started"
379 $docker_path start
$attach_on_start `cat $cidfile`
391 # Is the image available?
392 # If not, pull it here so the user is aware what's happening.
393 $docker_path history $image >/dev
/null
2>&1 ||
$docker_path pull
$image
397 base_image
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
398 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
400 update_pups
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
401 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
403 if [[ ! X
"" = X
"$base_image" ]]; then
412 run_command
="cd /pups &&"
413 if [[ ! "false" = $update_pups ]]; then
414 run_command
="$run_command git pull &&"
416 run_command
="$run_command /pups/bin/pups --stdin"
420 env
=("${env[@]}" "-e" "SSH_PUB_KEY=$ssh_pub_key")
422 (exec echo "$input" |
$docker_path run
$links "${env[@]}" -e DOCKER_HOST_IP
=$docker_ip --cidfile $cidbootstrap -i -a stdin
-a stdout
-a stderr
$volumes $image \
423 /bin
/bash
-c "$run_command") \
424 ||
($docker_path rm `cat $cidbootstrap` && rm $cidbootstrap)
426 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
430 $docker_path commit
`cat $cidbootstrap` $local_discourse/$config ||
echo 'FAILED TO COMMIT'
431 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
437 echo "Successfully bootstrapped, to startup use ./launcher start $config"
454 if [ ! $UID -eq 0 ] ;
456 echo "enter command must run as root, will attempt to sudo"
460 if [ ! -e bin
/nsenter
]
462 echo "Downloading nsenter"
463 $docker_path pull samsaffron
/nsenter
464 ($docker_path run
--rm samsaffron
/nsenter
cat /nsenter
> bin
/nsenter1
) ||
exit 1
465 cp bin
/nsenter1 bin
/nsenter
469 PID
=$
($docker_path inspect
--format {{.State.Pid
}} `cat $cidfile`)
470 SHELL
=/bin
/bash sudo
-E bin
/nsenter
--target $PID --mount --uts --ipc --net --pid
482 address
="`$docker_path port $cid 22`"
483 split=(${address//:/ })
484 exec ssh -o StrictHostKeyChecking
=no root@
${split[0]} -p ${split[1]}
500 $docker_path logs
`cat $cidfile`
517 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
518 echo "Updating discourse docker"
519 git pull ||
(echo 'failed to update' && exit 1)
523 echo "Stopping old container"
524 $docker_path stop
-t 10 `cat $cidfile`
531 $docker_path rm `cat $cidfile` && rm $cidfile
542 echo "destroying container $cidfile"
543 $docker_path stop
-t 10 `cat $cidfile`
544 $docker_path rm `cat $cidfile` && rm $cidfile
547 echo "nothing to destroy cidfile does not exist"