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
131 if [[ ! -e ~
/.ssh
/id_rsa.pub
&& ! -e ~
/.ssh
/id_dsa.pub
]] ; then
132 echo "This user has no SSH key, but a SSH key is required to access the Discourse Docker container."
133 read -p "Generate a SSH key? (Y/n) " -n 1 -r
134 if [[ $REPLY =~ ^
[Nn
]$
]] ; then
136 echo WARNING
: You may not be able to log
in to your container.
140 echo Generating SSH key
141 mkdir
-p ~
/.
ssh && ssh-keygen
-f ~
/.ssh
/id_rsa
-t rsa
-N ''
147 ssh_pub_key
="$(cat ~/.ssh/id_rsa.pub 2>/dev/null || cat ~/.ssh/id_dsa.pub)"
153 echo "Docker is not installed, make sure you are running on the 3.8 kernel"
154 echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
156 echo "sudo apt-get update"
157 echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
161 echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
162 echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
163 echo "sudo apt-get update"
164 echo "sudo apt-get install lxc-docker"
170 read -r -d '' env_ruby
<< 'RUBY'
173 input
= STDIN.readlines.
join
174 yaml
= YAML.load
(input
)
176 if host_run
= yaml
['host_run']
177 params
= yaml
['params'] ||
{}
178 host_run.each
do |run|
180 run
= run.gsub
("$#{k}", v
)
182 STDOUT.
write "#{run}--SEP--"
187 host_run
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
189 while [ "$host_run" ] ; do
190 iter
=${host_run%%--SEP--*}
192 echo "Host run: $iter"
195 host_run
="${host_run#*--SEP--}"
201 volumes
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
202 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
206 links
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
207 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
210 set_template_info
() {
212 templates
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
213 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
216 arrTemplates
=(${templates// / })
217 config_data
=$
(cat $config_file)
222 for template
in "${arrTemplates[@]}"
224 [ ! -z $template ] && {
225 input
="$input _FILE_SEPERATOR_ $(cat $template)"
229 # we always want our config file last so it takes priority
230 input
="$input _FILE_SEPERATOR_ $config_data"
232 read -r -d '' env_ruby
<< 'RUBY'
235 input
=STDIN.readlines.
join
236 # default to UTF-8 for the dbs sake
237 env
= {'LANG' => 'en_US.UTF-8'}
238 input.
split('_FILE_SEPERATOR_').each
do |yml|
241 env.merge
!(YAML.load
(yml
)['env'] ||
{})
242 rescue Psych
::SyntaxError
=> e
250 puts env.map
{|k
,v|
"-e\n#{k}=#{v}" }.
join("\n")
253 raw
=`exec echo "$input" | $docker_path run --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
258 if [ "$i" == "*ERROR." ]; then
260 elif [ -n "$i" ]; then
265 if [ "$ok" -ne 1 ]; then
267 echo "YAML syntax error. Please check your /var/docker/containers/*.yml config files."
270 echo "Calculated ENV: ${env[@]}"
273 [ -z $docker_path ] && {
282 if [ ! -e $config_file ]
284 echo "Config file was not found, ensure $config_file exists"
286 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
291 docker_version
=($
($docker_path --version))
292 docker_version
=${test[2]//,/}
294 if compare_version
"1.2.0" "$docker_version"; then
295 echo "We recommend you upgrade docker, the version you are running has no restart policies, on reboot your container may not start up"
298 restart_policy
=${restart_policy:---restart=always}
303 if [ ! -e $config_file ]; then
304 echo "Config does not exist: $config_file" >&2
307 exec scripts
/mailtest
$config_file
316 $docker_path stop
-t 10 `cat $cidfile`
326 echo "No cid found, creating a new container"
327 ports
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
328 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
334 existing
=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
335 if [ ! -z $existing ]
337 echo "Found an existing container by its name, recovering cidfile, please rerun"
338 echo $existing > $cidfile
342 $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 \
343 $volumes $local_discourse/$config /sbin
/boot
351 echo "Detected empty cid file, deleting, please re-run"
356 found
=`$docker_path ps -q -a --no-trunc | grep $cid`
359 echo "Invalid cid file, deleting, please re-run"
364 echo "cid found, ensuring container is started"
365 $docker_path start
$attach_on_start `cat $cidfile`
377 # Is the image available?
378 # If not, pull it here so the user is aware what's happening.
379 $docker_path history $image >/dev
/null
2>&1 ||
$docker_path pull
$image
383 base_image
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
384 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
386 update_pups
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
387 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
389 if [[ ! X
"" = X
"$base_image" ]]; then
398 run_command
="cd /pups &&"
399 if [[ ! "false" = $update_pups ]]; then
400 run_command
="$run_command git pull &&"
402 run_command
="$run_command /pups/bin/pups --stdin"
406 env
=("${env[@]}" "-e" "SSH_PUB_KEY=$ssh_pub_key")
408 (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 \
409 /bin
/bash
-c "$run_command") \
410 ||
($docker_path rm `cat $cidbootstrap` && rm $cidbootstrap)
412 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
416 $docker_path commit
`cat $cidbootstrap` $local_discourse/$config ||
echo 'FAILED TO COMMIT'
417 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
423 echo "Successfully bootstrapped, to startup use ./launcher start $config"
440 if [ ! $UID -eq 0 ] ;
442 echo "enter command must run as root, will attempt to sudo"
446 if [ ! -e bin
/nsenter
]
448 echo "Downloading nsenter"
449 $docker_path pull samsaffron
/nsenter
450 ($docker_path run
--rm samsaffron
/nsenter
cat /nsenter
> bin
/nsenter1
) ||
exit 1
451 cp bin
/nsenter1 bin
/nsenter
455 PID
=$
($docker_path inspect
--format {{.State.Pid
}} `cat $cidfile`)
456 SHELL
=/bin
/bash sudo
-E bin
/nsenter
--target $PID --mount --uts --ipc --net --pid
468 address
="`$docker_path port $cid 22`"
469 split=(${address//:/ })
470 exec ssh -o StrictHostKeyChecking
=no root@
${split[0]} -p ${split[1]}
486 $docker_path logs
`cat $cidfile`
503 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
504 echo "Updating discourse docker"
505 git pull ||
(echo 'failed to update' && exit 1)
509 echo "Stopping old container"
510 $docker_path stop
-t 10 `cat $cidfile`
517 $docker_path rm `cat $cidfile` && rm $cidfile
528 echo "destroying container $cidfile"
529 $docker_path stop
-t 10 `cat $cidfile`
530 $docker_path rm `cat $cidfile` && rm $cidfile
533 echo "nothing to destroy cidfile does not exist"