部署 使用 Docker 部署应用如何执行脚本文件?

ithelloworld · 2015年11月16日 · 最后由 ithelloworld 回复于 2015年11月27日 · 11459 次阅读

我想用 Docker 部署一个 Rails 应用。

Dockerfile 的内容如下:

FROM ruby:2.2.2

ENV APP_HOME /myapp
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

ADD Gemfile $APP_HOME/Gemfile
ADD Gemfile.lock $APP_HOME/Gemfile.lock
ADD init.sh $APP_HOME/

RUN export LANG=C.UTF-8 && bundle install

ADD . $APP_HOME

CMD ["sh", "init.sh"]

init.sh 程序执行脚本内容如下:

#!/bin/sh
bundle exec rake db:setup
bundle exec rake db:seed_fu
bundle exec sidekiq -C config/sidekiq.yml
bundle exec rails server -b 0.0.0.0

当我编译完这个程序镜像:

docker build -t myapp .

运行它时:

docker run --name web -d -p 3000:3000 myapp

从日志中看到:

docker logs web
init.sh: 2: init.sh: bundle: not found
init.sh: 3: init.sh: bundle: not found
init.sh: 4: init.sh: bundle: not found
init.sh: 5: init.sh: bundle: not found

是执行 bundle 的路径问题,怎么指定正确的路径呢?

没看到安装 bundler 的命令,bundler 不是 Ruby 自带的。

#1 楼 @rei 执行 Dockerfile 中的 RUN export LANG=C.UTF-8 && bundle install 是可以使用的,执行外部的脚本就找不到了。

Docker 官方镜像提供的 Ruby 版本中安装了 bundle:

https://hub.docker.com/_/ruby/ https://github.com/docker-library/ruby/blob/74ee8aec9c17ea2134db8a8ef199cf092c829576/2.2/Dockerfile

把 init.sh 的

#!/bin/sh

换成

#!/bin/bash

看看。

#3 楼 @rei 这个试过,结果是一样的。并且把 #!/bin/sh 头部删除也是一样的。

CMD ["bash", "init.sh"]

#5 楼 @rei 使用这种方式重新编译一下,还是一样。

我不知道了。

#7 楼 @rei 没事,我再试试别的办法,谢谢~

@ithelloworld

我认为虽然你使用 WORKDIR 切换了工作目录,但是 CMD ["sh", "init.sh"] 这里的 init.sh 对于这个脚本来讲,它的工作目录应该不是 /myapp

在 init.sh 里面用绝对路径如何?

#!/bin/sh

APP_BIN_PATH=/myapp/bin

$APP_BIN_PATH/bundle exec rake db:setup
$APP_BIN_PATH/bundle exec rake db:seed_fu
$APP_BIN_PATH/bundle exec sidekiq -C config/sidekiq.yml
$APP_BIN_PATH/bundle exec rails server -b 0.0.0.0

RUN whereis bundle 看看 bundle 在哪。

#9 楼 @hz_qiuyuanxin #10 楼 @rei 谢谢回复。 原因找到了,单从这两个文件来讲是没问题的,CMD ["sh", "init.sh"] 也可以识别定义的 WORKDIR 目录。问题在于我运行编译好的镜像时,在别的地方传入了 PATH 环境变量,是我的错😅

如果你要使用 Docker 来交付你的 Rails 应用 可以在镜像 build 的时候来执行 bundle 命令 另外,不要在同一个容器内启动太多进程 最好把 sidekiq、rails 以及 redis 分成不同的容器来启动

#12 楼 @wuwx 谢谢回复。

目前是这样做的:

  • 应用程序编译成镜像
  • Redis 使用官方镜像
  • 数据库:开发环境使用官方镜像,生产环境使用 Google Cloud SQL

本来尝试用 docker-compose 来组织各种服务,如 db, redis, sidekiq, fluentd, web, etc,但还是用一个 Dockerfile 来编译并封装程序脚本,运行容器的时候去执行。 这种考虑的原因在于,一次编译,在各种环境都能运行(考虑到生产环境的特殊性)。

最终使用 Kubernetes 部署到 Google Container Engine。

#13 楼 @ithelloworld 你的 dockerfile 太复杂啦,这些逻辑官方的 image 已经都包含了,何必麻烦两遍

FROM ruby:2.2.2-onbuild

CMD "sh init.sh"

就行了。 另外,compose 还是值得效仿的,这个和 k8s 不矛盾

#14 楼 @fsword 最终这样处理的:

FROM rails:4.2.1
...
CMD ["sh", "init.sh"]

docker-compose 是好东西,但为什么和 k8s 不矛盾呢?本地环境还行,部署到生产环境要使用 k8s,那它就用不上了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号