diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a255da6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,42 @@ +FROM hub.goodrain.com/dc-deploy/cedar14 +MAINTAINER ethan + +# 时区设置 +RUN echo "Asia/Shanghai" > /etc/timezone;dpkg-reconfigure -f noninteractive tzdata + +ENV HOME /app + +RUN mkdir /app +RUN addgroup --quiet --gid 200 rain && \ + useradd rain --uid=200 --gid=200 --home-dir /app --no-create-home \ + --shell /bin/bash +RUN chown rain:rain /app +WORKDIR /app + +# 创建goodrain程序目录 +#RUN mkdir -pv /opt/bin + +# 下载grproxy,每次升级需要重新创建runner镜像 +#RUN wget http://lang.goodrain.me/public/gr-listener -O /opt/bin/gr-listener + +# 添加可执行权限 +#RUN chmod +x /opt/bin/* + +#ADD ./profile.d /tmp/profile.d + + +# add default port to expose (can be overridden) +ENV PORT 5000 +ENV RELEASE_DESC=__RELEASE_DESC__ + +EXPOSE 5000 + +# 配置crontab 权限 +RUN chmod 1777 /run && usermod -G crontab rain && chmod u+s /usr/bin/crontab && chmod u+s /usr/sbin/cron + +RUN mkdir /data && chown rain:rain /data + +ADD ./runner /runner +RUN chown rain:rain /runner/init +USER rain +ENTRYPOINT ["/runner/init"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c3d67e3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +Flynn is a trademark of Apollic Software, LLC. + +Copyright (c) 2013-2014 Apollic Software, LLC. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Apollic Software, LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..996f6f3 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Runner +用来运行 [builder](https://github.com/goodrain/builder) 制作的tgz文件,每一个源码构建的应用都是由runner镜像加载运行的。 + +## Runner 运行原理 + +通过标准输入,文件挂载或者URL的形式将 压缩后 的应用程序(代码,运行时)传入到Runner镜像并运行。镜像的入口文件会读取Procfile中的内容并运行。 + +## 如何使用 Runner +云帮安装后该镜像自动在计算节点拉取,不需要人工干预。下面主要介绍手动通过runner镜像运行builder生成的压缩包的场景。 + + +可以通过标准输入将压缩包载入到runner镜像,并运行: + +```bash +$ cat myslug.tgz | docker run -i -a stdin -a stdout goodrain.me/runner +``` + +压缩包的内容会在runner容器启动后解压到 `/app` 目录,在正式启动应用程序之前,会先导入代码目录下 `.profile.d` 中的文件,这里会有应用程序所需要的环境变量。 + +最终,runner镜像的引导程序会读取代码目录下的`Procfile`文件,并启动应用程序。如果用户代码根目录中没有该文件,在builer构建时会根据用户在创建应用向导中的选择自动生成。 diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..66182d9 --- /dev/null +++ b/release.sh @@ -0,0 +1,63 @@ +#!/bin/bash +set -xe + +image_name="runner" +release_type=$1 + +if [ "$release_type" == "" ];then + echo "please input release type (community | enterprise | all )" + exit 1 +elif [ "$release_type" == "all" ];then + enterprise_version=$2 + community_version=$3 +else + release_version=$2 +fi + +trap 'clean_tmp; exit' QUIT TERM EXIT + +# clear temp file +function clean_tmp() { + echo "clean temporary file..." + [ -f Dockerfile.release ] && rm -rf Dockerfile.release +} + +function release(){ + release_name=$1 # master | enterprise | community + release_version=${2:-latest} # latest | 3.2 | 2017.05 + + if [ "$release_name" == "master" ];then + branch_name=${release_name} + git checkout ${branch_name} + else + branch_name=${release_name}-${release_version} + git checkout ${branch_name} + fi + + echo "Pull newest code..." && sleep 3 + git pull + + # get commit sha + git_commit=$(git log -n 1 --pretty --format=%h) + + + # get git describe info + release_desc=${release_name}-${release_version}-${git_commit} + + sed "s/__RELEASE_DESC__/${release_desc}/" Dockerfile > Dockerfile.release + + docker build -t hub.goodrain.com/dc-deploy/${image_name}:${release_version} -f Dockerfile.release . + docker push hub.goodrain.com/dc-deploy/${image_name}:${release_version} +} + +case $release_type in +"community") + release $1 ${release_version} + ;; +"enterprise") + release $1 ${release_version} + ;; +"master") + release $1 + ;; +esac diff --git a/runner/init b/runner/init new file mode 100755 index 0000000..6669378 --- /dev/null +++ b/runner/init @@ -0,0 +1,75 @@ +#!/bin/bash +set -eo pipefail + +[ $DEBUG ] && set -x + +# catch init parameter +if [ "$1" == "version" ];then + echo $RELEASE_DESC + exit 0 +elif [ "$1" == "debug" ];then + /bin/bash +else + # $1 : start + # $2 : runner type [web] + action=${1:-start} + app_type=${2:-web} +fi + +if [[ -f /etc/environment_proxy ]]; then + source /etc/environment_proxy +fi + +## Load slug from Bind Mount, URL or STDIN + +export HOME=/app +mkdir -p $HOME + +sleep ${PAUSE:-0} + +if [ -f /tmp/slug/slug.tgz ]; then + tar -xzf /tmp/slug/slug.tgz -C $HOME || exit 1 +else + echo "slug file error !" && exit 1 +fi +cd $HOME + + +## Load profile.d and release config + +shopt -s nullglob +mkdir -p .profile.d + + +if [[ -s .release ]]; then + ruby -e "require 'yaml';(YAML.load_file('.release')['config_vars'] || {}).each{|k,v| puts \"#{k}='#{v}'\"}" > .profile.d/config_vars +fi + +# 复制grproxy 启动文件 +#cp /tmp/profile.d/grproxy.sh .profile.d/grproxy.sh + + +# 运行 .profile.d 中的所有文件 +for file in .profile.d/*; do + source $file +done +hash -r + +## Inject "start" command to run processes defined in Procfile + +case "$action" in + start) + if [[ -f Procfile ]]; then + command="$(ruby -e "require 'yaml';puts YAML.load_file('Procfile')['$app_type']")" + else + command="$(ruby -e "require 'yaml';puts (YAML.load_file('.release')['default_process_types'] || {})['$app_type']")" + fi + ;; + + *) + command="$@" + ;; +esac + +## Run! +exec bash -c "$command"