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.7
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"
56 echo " --docker-args Extra arguments to pass when running docker"
63 IFS
=.
read -a ver_a
<<< "$1"
64 IFS
=.
read -a ver_b
<<< "$2"
66 while [[ -n $ver_a ]]; do
67 if (( ver_a
> ver_b
)); then
69 elif (( ver_b
> ver_a
)); then
78 return 1 # They are equal
83 # 1. docker daemon running?
84 test=`$docker_path info >/dev/null`
86 if [[ $?
-ne 0 ]] ; then
87 echo "Cannot connect to the docker daemon - verify it is running and you have access"
91 # 2. running aufs or btrfs
92 test=`$docker_path info 2> /dev/null | grep 'Driver: '`
93 if [[ "$test" =~
[aufs|btrfs
] ]] ; then : ; else
94 echo "Your Docker installation is not using the recommended AuFS (union filesystem) and may be unstable."
95 echo "If you are unable to bootstrap / stop your image please report the issue at:"
96 echo "https://meta.discourse.org/t/discourse-docker-installation-without-aufs/15639"
99 # 3. running recommended docker version
100 test=($
($docker_path --version)) # Get docker version string
101 test=${test[2]//,/} # Get version alone and strip comma if exists
103 [[ "$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
105 # At least minimum version
106 if compare_version
"${docker_min_version}" "${test}"; then
107 echo "ERROR: Docker version ${test} not supported, please upgrade to at least ${docker_min_version}, or recommended ${docker_rec_version}"
111 # Recommend best version
112 if compare_version
"${docker_rec_version}" "${test}"; then
113 echo "WARNING: Docker version ${test} deprecated, recommend upgrade to ${docker_rec_version} or newer."
116 # 4. able to attach stderr / out / tty
117 test=`$docker_path run $user_args -i --rm -a stdout -a stderr $image echo working`
118 if [[ "$test" =~
"working" ]] ; then : ; else
119 echo "Your Docker installation is not working correctly"
121 echo "See: https://meta.discourse.org/t/docker-error-on-bootstrap/13657/18?u=sam"
126 if [ "$opt" != "--skip-prereqs" ] ; then
130 if [ "$opt" == "--docker-args" ] ; then
137 local ${ssh_key_locations}
139 ~
/.ssh
/id_ed25519.pub
143 ~core
/.ssh
/authorized_keys
147 for keyfile
in "${ssh_key_locations[@]}"; do
148 if [[ -e ${keyfile} ]] ; then
149 ssh_pub_key
="$(cat ${keyfile})"
155 echo "This user has no SSH key, but a SSH key is required to access the Discourse Docker container."
156 read -p "Generate a SSH key? (Y/n) " -n 1 -r
157 if [[ $REPLY =~ ^
[Nn
]$
]] ; then
159 echo WARNING
: You may not be able to log
in to your container.
163 echo Generating SSH key
164 mkdir
-p ~
/.
ssh && ssh-keygen
-f ~
/.ssh
/id_rsa
-t rsa
-N ''
166 ssh_pub_key
="$(cat ~/.ssh/id_rsa.pub)"
177 echo "Docker is not installed, make sure you are running on the 3.8 kernel"
178 echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
180 echo "sudo apt-get update"
181 echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
185 echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
186 echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
187 echo "sudo apt-get update"
188 echo "sudo apt-get install lxc-docker"
194 read -r -d '' env_ruby
<< 'RUBY'
197 input
= STDIN.readlines.
join
198 yaml
= YAML.load
(input
)
200 if host_run
= yaml
['host_run']
201 params
= yaml
['params'] ||
{}
202 host_run.each
do |run|
204 run
= run.gsub
("$#{k}", v
)
206 STDOUT.
write "#{run}--SEP--"
211 host_run
=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e "$env_ruby"`
213 while [ "$host_run" ] ; do
214 iter
=${host_run%%--SEP--*}
216 echo "Host run: $iter"
219 host_run
="${host_run#*--SEP--}"
225 volumes
=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
226 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
230 links
=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
231 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['links'].map{|l| '--link ' << l['link']['name'] << ':' << l['link']['alias'] << ' '}.join"`
234 set_template_info
() {
236 templates
=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
237 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
240 arrTemplates
=(${templates// / })
241 config_data
=$
(cat $config_file)
246 for template
in "${arrTemplates[@]}"
248 [ ! -z $template ] && {
249 input
="$input _FILE_SEPERATOR_ $(cat $template)"
253 # we always want our config file last so it takes priority
254 input
="$input _FILE_SEPERATOR_ $config_data"
256 read -r -d '' env_ruby
<< 'RUBY'
259 input
=STDIN.readlines.
join
260 # default to UTF-8 for the dbs sake
261 env
= {'LANG' => 'en_US.UTF-8'}
262 input.
split('_FILE_SEPERATOR_').each
do |yml|
265 env.merge
!(YAML.load
(yml
)['env'] ||
{})
266 rescue Psych
::SyntaxError
=> e
274 puts env.map
{|k
,v|
"-e\n#{k}=#{v}" }.
join("\n")
277 raw
=`exec echo "$input" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
282 if [ "$i" == "*ERROR." ]; then
284 elif [ -n "$i" ]; then
289 if [ "$ok" -ne 1 ]; then
291 echo "YAML syntax error. Please check your /var/discourse/containers/*.yml config files."
294 echo "Calculated ENV: ${env[@]}"
297 [ -z $docker_path ] && {
306 if [ ! -e $config_file ]
308 echo "Config file was not found, ensure $config_file exists"
310 echo "Available configs ( `cd containers && ls -dm *.yml | tr -s '\n' ' ' | awk '{ gsub(/\.yml/, ""); print }'`)"
315 docker_version
=($
($docker_path --version))
316 docker_version
=${test[2]//,/}
318 if compare_version
"1.2.0" "$docker_version"; then
319 echo "We recommend you upgrade docker, the version you are running has no restart policies, on reboot your container may not start up"
322 restart_policy
=${restart_policy:---restart=always}
327 if [ ! -e $config_file ]; then
328 echo "Config does not exist: $config_file" >&2
331 exec scripts
/mailtest
$config_file
340 $docker_path stop
-t 10 `cat $cidfile`
350 echo "No cid found, creating a new container"
351 ports
=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
352 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
358 existing
=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
359 if [ ! -z $existing ]
361 echo "Found an existing container by its name, recovering cidfile, please rerun"
362 echo $existing > $cidfile
366 $docker_path run
$user_args $links $attach_on_run $restart_policy "${env[@]}" -h "`hostname`-$config" -e DOCKER_HOST_IP
=$docker_ip --name $config -t --cidfile $cidfile $ports \
367 $volumes $local_discourse/$config /sbin
/boot
375 echo "Detected empty cid file, deleting, please re-run"
380 found
=`$docker_path ps -q -a --no-trunc | grep $cid`
383 echo "Invalid cid file, deleting, please re-run"
388 echo "cid found, ensuring container is started"
389 $docker_path start
$attach_on_start `cat $cidfile`
401 # Is the image available?
402 # If not, pull it here so the user is aware what's happening.
403 $docker_path history $image >/dev
/null
2>&1 ||
$docker_path pull
$image
407 base_image
=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
408 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
410 update_pups
=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
411 "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
413 if [[ ! X
"" = X
"$base_image" ]]; then
422 run_command
="cd /pups &&"
423 if [[ ! "false" = $update_pups ]]; then
424 run_command
="$run_command git pull &&"
426 run_command
="$run_command /pups/bin/pups --stdin"
430 env
=("${env[@]}" "-e" "SSH_PUB_KEY=$ssh_pub_key")
432 (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 \
433 /bin
/bash
-c "$run_command") \
434 ||
($docker_path rm `cat $cidbootstrap` && rm $cidbootstrap)
436 [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
440 $docker_path commit
`cat $cidbootstrap` $local_discourse/$config ||
echo 'FAILED TO COMMIT'
441 $docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
447 echo "Successfully bootstrapped, to startup use ./launcher start $config"
464 if [ ! $UID -eq 0 ] ;
466 echo "enter command must run as root, will attempt to sudo"
470 if [ ! -e bin
/nsenter
]
472 echo "Downloading nsenter"
473 $docker_path pull samsaffron
/nsenter
474 ($docker_path run
$user_args --rm samsaffron
/nsenter
cat /nsenter
> bin
/nsenter1
) ||
exit 1
475 cp bin
/nsenter1 bin
/nsenter
479 PID
=$
($docker_path inspect
--format {{.State.Pid
}} `cat $cidfile`)
480 SHELL
=/bin
/bash sudo
-E bin
/nsenter
--target $PID --mount --uts --ipc --net --pid
492 address
="`$docker_path port $cid 22`"
493 split=(${address//:/ })
494 exec ssh -o StrictHostKeyChecking
=no root@
${split[0]} -p ${split[1]}
510 $docker_path logs
`cat $cidfile`
527 if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
528 echo "Updating discourse docker"
529 git pull ||
(echo 'failed to update' && exit 1)
533 echo "Stopping old container"
534 $docker_path stop
-t 10 `cat $cidfile`
541 $docker_path rm `cat $cidfile` && rm $cidfile
552 echo "destroying container $cidfile"
553 $docker_path stop
-t 10 `cat $cidfile`
554 $docker_path rm `cat $cidfile` && rm $cidfile
557 echo "nothing to destroy cidfile does not exist"