9 docker_min_version
='0.9.1'
10 docker_rec_version
='0.11.1'
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.0
17 docker_path
=`which docker.io || which docker`
19 docker_ip
=`/sbin/ifconfig | \
20 grep -B1 "inet addr" | \
21 awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' | \
23 awk -F: '{ print $3 }';`
27 echo "Usage: launcher COMMAND CONFIG [--skip-prereqs]"
29 echo " start: Start/initialize a container"
30 echo " stop: Stop a running container"
31 echo " restart: Restart a container"
32 echo " destroy: Stop and remove a container"
33 echo " enter: Use nsenter to enter a container"
34 echo " ssh: Start a bash shell in a running container"
35 echo " logs: Docker logs for container"
36 echo " mailtest: Test the mail settings in a container"
37 echo " bootstrap: Bootstrap a container for the config based on a template"
38 echo " rebuild: Rebuild a container (destroy old, bootstrap, start new)"
41 echo " --skip-prereqs Don't check prerequisites"
48 IFS
=.
read -a ver_a
<<< "$1"
49 IFS
=.
read -a ver_b
<<< "$2"
51 while [[ -n $ver_a ]]; do
52 if (( ver_a
> ver_b
)); then
54 elif (( ver_b
> ver_a
)); then
63 return 1 # They are equal
68 # 1. docker daemon running?
69 test=`$docker_path info >/dev/null`
71 if [[ $?
-ne 0 ]] ; then
72 echo "Cannot connect to the docker daemon - verify it is running and you have access"
77 test=`$docker_path info 2> /dev/null | grep 'Driver: aufs'`
78 if [[ "$test" =~
"aufs" ]] ; then : ; else
79 echo "Your Docker installation is not using aufs, in the past we have had issues with it"
80 echo "If you are unable to bootstrap your image (or stop it) please report the issue at:"
81 echo "https://meta.discourse.org/t/discourse-docker-installation-without-aufs/15639"
84 # 3. running recommended docker version
85 test=($
($docker_path --version)) # Get docker version string
86 test=${test[2]//,/} # Get version alone and strip comma if exists
88 [[ "$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
90 # At least minimum version
91 if compare_version
"${docker_min_version}" "${test}"; then
92 echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
96 # Recommend best version
97 if compare_version
"${docker_rec_version}" "${test}"; then
98 echo "WARNING: Docker version ${test} deprecated, recommend upgrade to ${docker_rec_version} or newer."
101 # 4. able to attach stderr / out / tty
102 test=`$docker_path run -i --rm -a stdout -a stderr $image echo working`
103 if [[ "$test" =~
"working" ]] ; then : ; else
104 echo "Your Docker installation is not working correctly"
106 echo "See: https://meta.discourse.org/t/docker-error-on-bootstrap/13657/18?u=sam"
111 if [ "$opt" != "--skip-prereqs" ] ; then
117 if [[ ! -e ~
/.ssh
/id_rsa.pub
&& ! -e ~
/.ssh
/id_dsa.pub
]] ; then
118 echo "This user has no SSH key, but a SSH key is required to access the Discourse Docker container."
119 read -p "Generate a SSH key? (Y/n) " -n 1 -r
120 if [[ $REPLY =~ ^
[Nn
]$
]] ; then
122 echo WARNING
: You may not be able to log
in to your container.
126 echo Generating SSH key
127 mkdir
-p ~
/.
ssh && ssh-keygen
-f ~
/.ssh
/id_rsa
-t rsa
-N ''
133 ssh_pub_key
="$(cat ~/.ssh/id_rsa.pub 2>/dev/null || cat ~/.ssh/id_dsa.pub)"
139 echo "Docker is not installed, make sure you are running on the 3.8 kernel"
140 echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
142 echo "sudo apt-get update"
143 echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
147 echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
148 echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
149 echo "sudo apt-get update"
150 echo "sudo apt-get install lxc-docker"
156 volumes
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
157 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
160 set_template_info
() {
162 templates
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
163 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
166 arrTemplates
=(${templates// / })
167 config_data
=$
(cat $config_file)
172 for template
in "${arrTemplates[@]}"
174 [ ! -z $template ] && {
175 input
="$input _FILE_SEPERATOR_ $(cat $template)"
179 # we always want our config file last so it takes priority
180 input
="$input _FILE_SEPERATOR_ $config_data"
182 read -r -d '' env_ruby
<< 'RUBY'
185 input
=STDIN.readlines.
join
186 # default to UTF-8 for the dbs sake
187 env
= {'LANG' => 'en_US.UTF-8'}
188 input.
split('_FILE_SEPERATOR_').each
do |yml|
191 env.merge
!(YAML.load
(yml
)['env'] ||
{})
192 rescue Psych
::SyntaxError
=> e
200 puts env.map
{|k
,v|
"-e\n#{k}=#{v}" }.
join("\n")
203 raw
=`exec echo "$input" | $docker_path run --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
208 if [ "$i" == "*ERROR." ]; then
210 elif [ -n "$i" ]; then
215 if [ "$ok" -ne 1 ]; then
217 echo "YAML syntax error. Please check your /var/docker/containers/*.yml config files."
220 echo "Calculated ENV: ${env[@]}"
223 [ -z $docker_path ] && {
232 if [ ! -e $config_file ]
234 echo "Config file was not found, ensure $config_file exists"
236 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
242 if [ ! -e $config_file ]; then
243 echo "Config does not exist: $config_file" >&2
246 exec scripts
/mailtest
$config_file
255 $docker_path stop
-t 10 `cat $cidfile`
263 echo "No cid found, creating a new container"
264 ports
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
265 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
270 existing
=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
271 if [ ! -z $existing ]
273 echo "Found an existing container by its name, recovering cidfile, please rerun"
274 echo $existing > $cidfile
278 $docker_path run
"${env[@]}" -h "`hostname`-$config" -e DOCKER_HOST_IP
=$docker_ip --name $config -t --cidfile $cidfile $ports \
279 -d $volumes $local_discourse/$config /sbin
/runit
287 echo "Detected empty cid file, deleting, please re-run"
292 found
=`$docker_path ps -q -a --no-trunc | grep $cid`
295 echo "Invalid cid file, deleting, please re-run"
300 echo "cid found, ensuring container is started"
301 $docker_path start
`cat $cidfile`
310 # Is the image available?
311 # If not, pull it here so the user is aware what's happening.
312 $docker_path history $image >/dev
/null
2>&1 ||
$docker_path pull
$image
316 base_image
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
317 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
319 update_pups
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
320 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
322 if [[ ! X
"" = X
"$base_image" ]]; then
330 run_command
="cd /pups &&"
331 if [[ ! "false" = $update_pups ]]; then
332 run_command
="$run_command git pull &&"
334 run_command
="$run_command /pups/bin/pups --stdin"
338 env
=("${env[@]}" "-e" "SSH_PUB_KEY=$ssh_pub_key")
340 (exec echo "$input" |
$docker_path run
"${env[@]}" -e DOCKER_HOST_IP
=$docker_ip --cidfile $cidbootstrap -i -a stdin
-a stdout
-a stderr
$volumes $image \
341 /bin
/bash
-c "$run_command") \
342 ||
($docker_path rm `cat $cidbootstrap` && rm $cidbootstrap)
344 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
348 $docker_path commit
`cat $cidbootstrap` $local_discourse/$config ||
echo 'FAILED TO COMMIT'
349 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
355 echo "Successfully bootstrapped, to startup use ./launcher start $config"
372 if [ ! $UID -eq 0 ] ;
374 echo "enter command must run as root, will attempt to sudo"
378 if [ ! -e bin
/nsenter
]
380 echo "Downloading nsenter"
381 $docker_path pull samsaffron
/nsenter
382 ($docker_path run
--rm samsaffron
/nsenter
cat /nsenter
> bin
/nsenter1
) ||
exit 1
383 cp bin
/nsenter1 bin
/nsenter
387 PID
=$
($docker_path inspect
--format {{.State.Pid
}} `cat $cidfile`)
388 SHELL
=/bin
/bash sudo
-E bin
/nsenter
--target $PID --mount --uts --ipc --net --pid
400 address
="`$docker_path port $cid 22`"
401 split=(${address//:/ })
402 exec ssh -o StrictHostKeyChecking
=no root@
${split[0]} -p ${split[1]}
418 $docker_path logs
`cat $cidfile`
435 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
436 echo "Updating discourse docker"
437 git pull ||
(echo 'failed to update' && exit 1)
441 echo "Stopping old container"
442 $docker_path stop
-t 10 `cat $cidfile`
449 $docker_path rm `cat $cidfile` && rm $cidfile
460 echo "destroying container $cidfile"
461 $docker_path stop
-t 10 `cat $cidfile`
462 $docker_path rm `cat $cidfile` && rm $cidfile
465 echo "nothing to destroy cidfile does not exist"