re='[A-Z/ !@#$%^&*()+~`=]'
if [[ $config =~ $re ]];
then
- echo
+ echo
echo "ERROR: Config name must not contain upper case characters, spaces or special characters. Correct config name and rerun $0."
echo
exit 1
cd "$(dirname "$0")"
-docker_min_version='1.2.0'
-docker_rec_version='1.2.0'
+docker_min_version='1.6.0'
+docker_rec_version='1.6.0'
config_file=containers/"$config".yml
cidbootstrap=cids/"$config"_bootstrap.cid
local_discourse=local_discourse
-image=discourse/discourse:1.0.14
+image=discourse/discourse:1.0.17
docker_path=`which docker.io || which docker`
+template_path=samples/standalone_template.yml
+changelog=/tmp/changelog # used to test whether sed did anything
if [ "${SUPERVISED}" = "true" ]; then
restart_policy="--restart=no"
echo " logs: Docker logs for container"
echo " bootstrap: Bootstrap a container for the config based on a template"
echo " rebuild: Rebuild a container (destroy old, bootstrap, start new)"
+ echo " memconfig: Configure defaults based on available RAM"
echo " cleanup: Remove all containers that have stopped for > 24 hours"
echo
echo "Options:"
- echo " --skip-prereqs Don't check prerequisites"
+ echo " --skip-prereqs Don't check prerequisites or resource requirements"
echo " --docker-args Extra arguments to pass when running docker"
exit 1
}
fi
}
+check_ports() {
+ local valid=$(netstat -tln | awk '{print $4}' | grep ":${1}\$")
+
+ if [ -n "$valid" ]; then
+ echo "Launcher has detected that port ${1} is in use."
+ echo ""
+ echo "If you are trying to run Discourse simultaneously with another web server like Apache or nginx, you will need to bind to a different port."
+ echo "See https://meta.discourse.org/t/17247 for help."
+ echo "To continue anyway, re-run Launcher with --skip-prereqs"
+ exit 1
+ fi
+}
+
if [ "$opt" != "--skip-prereqs" ] ; then
prereqs
fi
usage
}
-if [ ! -e $config_file ]
+if [[ ! -e $config_file && $command -ne "memconfig" ]]
then
echo "Config file was not found, ensure $config_file exists"
echo ""
fi
}
+set_run_image() {
+ run_image=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
+ "require 'yaml'; puts YAML.load(STDIN.readlines.join)['run_image']"`
+
+ if [ -z "$run_image" ]; then
+ run_image="$local_discourse/$config"
+ fi
+}
+
+set_boot_command() {
+ boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
+ "require 'yaml'; puts YAML.load(STDIN.readlines.join)['boot_command']"`
+
+ if [ -z "$boot_command" ]; then
+
+ no_boot_command=`cat $config_file | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e \
+ "require 'yaml'; puts YAML.load(STDIN.readlines.join)['no_boot_command']"`
+
+ if [ -z "$no_boot_command" ]; then
+ boot_command="/sbin/boot"
+ fi
+ fi
+}
+
+run_memconfig(){
+ if [ "$opt" != "--skip-prereqs" ] ; then
+ check_resources
+ fi
+ if [ -f $config_file ]
+ then
+ cp $config_file $config_file.bak
+ echo "Saving $config_file as $config_file.bak"
+ else
+ echo "Creating $config_file from $template_path"
+ if [ ! -f $template_path ]
+ then
+ echo "$template_path is missing. Exiting."
+ exit 1
+ fi
+ cp $template_path $config_file
+ fi
+
+ # get free mem
+ avail_mem="$(LANG=C free -m | grep '^Mem:' | awk '{print $2}')"
+ avail_gb=`expr $(($avail_mem / 950))`
+ avail_cores=`grep -c processor /proc/cpuinfo`
+ echo "Found $avail_mem (${avail_gb}GB), of memory and $avail_cores cores."
+
+ # set db_shared_buffers: "128MB" (1GB) or 256MB * GB
+ if [ "$avail_gb" -eq "1" ]
+ then
+ db_shared_buffers="128"
+ else
+ db_shared_buffers=`expr $avail_gb \* 256`
+ fi
+ echo -e "Setting db_shared_buffers to ${db_shared_buffers}GB\c"
+ sed -i -e "s/^ db_shared_buffers:.*/ db_shared_buffers: \"${db_shared_buffers}GB\"/w $changelog" $config_file
+ if [ -s $changelog ]
+ then
+ echo " successfully."
+ rm $changelog
+ else
+ echo -e ". . . oops!\n---> db_shared_buffers not found in $config_file. Retaining defaults."
+ fi
+
+ # set UNICORN_WORKERS: 2*GB or 2*cores (the same on DO)
+ if [ "$avail_gb" -le "2" ]
+ then
+ unicorn_workers=`expr $avail_gb \* 2`
+ else
+ unicorn_workers=`expr $avail_cores \* 2`
+ fi
+
+ echo -e "Setting UNICORN_WORKERS to $unicorn_workers\c"
+ sed -i -e "s/^ UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
+ if [ -s $changelog ]
+ then
+ echo " successfully."
+ rm $changelog
+ else
+ echo -e ". . . oops!\n---> UNICORN_WORKERS not found in $config_file. Retaining defaults.\n"
+ fi
+}
+
run_start(){
existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
host_run
ports=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
- "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
+ "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| \"-p #{p}\"}.join(' ')"`
+
+ IFS='-p ' read -a array <<< "$ports"
+ for element in "${array[@]}"
+ do
+ IFS=':' read -a args <<< "$element"
+ if [ "${#args[@]}" == "2" ]; then
+ check_ports "${args[0]}"
+ elif [ "${#args[@]}" == "3" ]; then
+ check_ports "${args[1]}"
+ fi
+ done
docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
"require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
set_template_info
set_volumes
set_links
+ set_run_image
+ set_boot_command
+
+ # get hostname and settings from container configuration
+ for envar in "${env[@]}"
+ do
+ if [[ $envar == DOCKER_USE_HOSTNAME* ]] || [[ $envar == DISCOURSE_HOSTNAME* ]]
+ then
+ # use as environment variable
+ eval $envar
+ fi
+ done
(
- hostname=`hostname`
+ hostname=`hostname -s`
+ # overwrite hostname
+ if [ "$DOCKER_USE_HOSTNAME" = "true" ]
+ then
+ hostname=$DISCOURSE_HOSTNAME
+ else
+ hostname=$hostname-$config
+ fi
+
+ # we got to normalize so we only have allowed strings, this is more comprehensive but lets see how bash does first
+ # hostname=`$docker_path run $user_args --rm $image ruby -e 'print ARGV[0].gsub(/[^a-zA-Z-]/, "-")' $hostname`
+ # docker added more hostname rules
+ hostname=${hostname/_/-}
+
set -x
- $docker_path run $user_args $links $attach_on_run $restart_policy "${env[@]}" -h "$hostname-$config" \
- -e DOCKER_HOST_IP=$docker_ip --name $config -t $ports $volumes $docker_args $local_discourse/$config \
- /sbin/boot
+ $docker_path run $user_args $links $attach_on_run $restart_policy "${env[@]}" -h "$hostname" \
+ -e DOCKER_HOST_IP=$docker_ip --name $config -t $ports $volumes $docker_args $run_image $boot_command
)
exit 0
run_bootstrap(){
- check_resources
+ if [ "$opt" != "--skip-prereqs" ] ; then
+ check_resources
+ fi
host_run
$docker_path rm `cat $cidbootstrap` && rm $cidbootstrap
}
+
+
case "$command" in
bootstrap)
run_bootstrap
;;
enter)
- exec $docker_path exec -it $config /bin/bash
+ exec $docker_path exec -it $config /bin/bash --login
;;
ssh)
exit 0
;;
+ memconfig)
+ run_memconfig
+ exit 0
+ ;;
+
rebuild)
if [ "$(git symbolic-ref --short HEAD)" == "master" ]; then
echo "Ensuring discourse docker is up to date"