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.6
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}
132 ~
/.ssh
/id_ed25519.pub
136 ~core
/.ssh
/authorized_keys
140 for keyfile
in "${ssh_key_locations[@]}"; do
141 if [[ -e ${keyfile} ]] ; then
142 ssh_pub_key
="$(cat ${keyfile})"
148 echo "This user has no SSH key, but a SSH key is required to access the Discourse Docker container."
149 read -p "Generate a SSH key? (Y/n) " -n 1 -r
150 if [[ $REPLY =~ ^
[Nn
]$
]] ; then
152 echo WARNING
: You may not be able to log
in to your container.
156 echo Generating SSH key
157 mkdir
-p ~
/.
ssh && ssh-keygen
-f ~
/.ssh
/id_rsa
-t rsa
-N ''
159 ssh_pub_key
="$(cat ~/.ssh/id_rsa.pub)"
170 echo "Docker is not installed, make sure you are running on the 3.8 kernel"
171 echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
173 echo "sudo apt-get update"
174 echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
178 echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
179 echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
180 echo "sudo apt-get update"
181 echo "sudo apt-get install lxc-docker"
187 read -r -d '' env_ruby
<< 'RUBY'
190 input
= STDIN.readlines.
join
191 yaml
= YAML.load
(input
)
193 if host_run
= yaml
['host_run']
194 params
= yaml
['params'] ||
{}
195 host_run.each
do |run|
197 run
= run.gsub
("$#{k}", v
)
199 STDOUT.
write "#{run}--SEP--"
204 host_run
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
206 while [ "$host_run" ] ; do
207 iter
=${host_run%%--SEP--*}
209 echo "Host run: $iter"
212 host_run
="${host_run#*--SEP--}"
218 volumes
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
219 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
223 links
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
224 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
227 set_template_info
() {
229 templates
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
230 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
233 arrTemplates
=(${templates// / })
234 config_data
=$
(cat $config_file)
239 for template
in "${arrTemplates[@]}"
241 [ ! -z $template ] && {
242 input
="$input _FILE_SEPERATOR_ $(cat $template)"
246 # we always want our config file last so it takes priority
247 input
="$input _FILE_SEPERATOR_ $config_data"
249 read -r -d '' env_ruby
<< 'RUBY'
252 input
=STDIN.readlines.
join
253 # default to UTF-8 for the dbs sake
254 env
= {'LANG' => 'en_US.UTF-8'}
255 input.
split('_FILE_SEPERATOR_').each
do |yml|
258 env.merge
!(YAML.load
(yml
)['env'] ||
{})
259 rescue Psych
::SyntaxError
=> e
267 puts env.map
{|k
,v|
"-e\n#{k}=#{v}" }.
join("\n")
270 raw
=`exec echo "$input" | $docker_path run --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
275 if [ "$i" == "*ERROR." ]; then
277 elif [ -n "$i" ]; then
282 if [ "$ok" -ne 1 ]; then
284 echo "YAML syntax error. Please check your /var/docker/containers/*.yml config files."
287 echo "Calculated ENV: ${env[@]}"
290 [ -z $docker_path ] && {
299 if [ ! -e $config_file ]
301 echo "Config file was not found, ensure $config_file exists"
303 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
308 docker_version
=($
($docker_path --version))
309 docker_version
=${test[2]//,/}
311 if compare_version
"1.2.0" "$docker_version"; then
312 echo "We recommend you upgrade docker, the version you are running has no restart policies, on reboot your container may not start up"
315 restart_policy
=${restart_policy:---restart=always}
320 if [ ! -e $config_file ]; then
321 echo "Config does not exist: $config_file" >&2
324 exec scripts
/mailtest
$config_file
333 $docker_path stop
-t 10 `cat $cidfile`
343 echo "No cid found, creating a new container"
344 ports
=`cat $config_file | $docker_path run --rm -i -a stdout -a stdin $image ruby -e \
345 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
351 existing
=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
352 if [ ! -z $existing ]
354 echo "Found an existing container by its name, recovering cidfile, please rerun"
355 echo $existing > $cidfile
359 $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 \
360 $volumes $local_discourse/$config /sbin
/boot
368 echo "Detected empty cid file, deleting, please re-run"
373 found
=`$docker_path ps -q -a --no-trunc | grep $cid`
376 echo "Invalid cid file, deleting, please re-run"
381 echo "cid found, ensuring container is started"
382 $docker_path start
$attach_on_start `cat $cidfile`
394 # Is the image available?
395 # If not, pull it here so the user is aware what's happening.
396 $docker_path history $image >/dev
/null
2>&1 ||
$docker_path pull
$image
400 base_image
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
401 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
403 update_pups
=`cat $config_file | $docker_path run --rm -i -a stdin -a stdout $image ruby -e \
404 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
406 if [[ ! X
"" = X
"$base_image" ]]; then
415 run_command
="cd /pups &&"
416 if [[ ! "false" = $update_pups ]]; then
417 run_command
="$run_command git pull &&"
419 run_command
="$run_command /pups/bin/pups --stdin"
423 env
=("${env[@]}" "-e" "SSH_PUB_KEY=$ssh_pub_key")
425 (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 \
426 /bin
/bash
-c "$run_command") \
427 ||
($docker_path rm `cat $cidbootstrap` && rm $cidbootstrap)
429 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
433 $docker_path commit
`cat $cidbootstrap` $local_discourse/$config ||
echo 'FAILED TO COMMIT'
434 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
440 echo "Successfully bootstrapped, to startup use ./launcher start $config"
457 if [ ! $UID -eq 0 ] ;
459 echo "enter command must run as root, will attempt to sudo"
463 if [ ! -e bin
/nsenter
]
465 echo "Downloading nsenter"
466 $docker_path pull samsaffron
/nsenter
467 ($docker_path run
--rm samsaffron
/nsenter
cat /nsenter
> bin
/nsenter1
) ||
exit 1
468 cp bin
/nsenter1 bin
/nsenter
472 PID
=$
($docker_path inspect
--format {{.State.Pid
}} `cat $cidfile`)
473 SHELL
=/bin
/bash sudo
-E bin
/nsenter
--target $PID --mount --uts --ipc --net --pid
485 address
="`$docker_path port $cid 22`"
486 split=(${address//:/ })
487 exec ssh -o StrictHostKeyChecking
=no root@
${split[0]} -p ${split[1]}
503 $docker_path logs
`cat $cidfile`
520 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
521 echo "Updating discourse docker"
522 git pull ||
(echo 'failed to update' && exit 1)
526 echo "Stopping old container"
527 $docker_path stop
-t 10 `cat $cidfile`
534 $docker_path rm `cat $cidfile` && rm $cidfile
545 echo "destroying container $cidfile"
546 $docker_path stop
-t 10 `cat $cidfile`
547 $docker_path rm `cat $cidfile` && rm $cidfile
550 echo "nothing to destroy cidfile does not exist"