当构buildDockerfile时,linux source命令不起作用

我有一个定义Ruby on Rails堆栈的Dockerfile。

这是Dockerfile:

FROM ubuntu:14.04 MAINTAINER example <examplen@example.com> # Update RUN apt-get update # Install Ruby and Rails dependencies RUN apt-get install -y \ ruby \ ruby-dev \ build-essential \ libxml2-dev \ libxslt1-dev \ zlib1g-dev \ libsqlite3-dev \ nodejs \ curl RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 RUN curl -sSL https://get.rvm.io | bash -s stable --rails RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm" # Install Rails RUN gem install rails # Create a new Rails app under /src/my-app RUN mkdir -p /src/new-app RUN rails new /src/new-app WORKDIR /src/my-app # Default command is to run a rails server on port 3000 CMD ["rails", "server", "--binding", "0.0.0.0", "--port" ,"3000"] EXPOSE 3000 

当我执行命令docker build -t anotherapp/my-rails-app . 我得到以下错误:

拆下中间容器3f8060cdc6f5
第8步:运行gem install rails
—>运行在8c1793414e63
错误:安装rails的错误:
主动支持需要Ruby版本> = 2.2.2。
命令'/ bin / sh -c gem install rails'返回一个非零的代码:1

它看起来像命令source /usr/local/rvm/scripts/rvm在构build期间不工作。

我不确定这是为什么发生。

从docker生成器参考中 ,每个RUN命令都是独立运行的。 所以RUN source /usr/local/rvm/scripts/rvm对下一个RUN命令没有任何影响。

尝试更改需要给定源文件的操作,如下所示

  RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm ; gem install rails" 

这不是直接回答你的问题,而是解决问题的另一种方法。

Docker提供了一个正式的 Ruby映像 。 这是Docker Compose和Rails快速入门教程使用的图像。 正如你可以从他们的例子中看到的,你可以将你的Gemfile.lock复制到你的映像中,并运行bundle install而不必担心RVM。

 FROM ruby:2.2.0 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock RUN bundle install ADD . /myapp 

通常情况下,只有一个使用特定版本的Ruby的容器在一个容器内运行,所以RVM能够pipe理多个版本的Ruby并不会有帮助。

如果你很好奇官方的图像是如何制作的, Dockerfile在Github上。


至于为什么发生这种情况。 正如其他人指出的那样, source命令在当前shell中执行该文件。 每个RUN指令

…将在当前图像的顶部执行新图层中的任何命令并提交结果。 生成的提交图像将用于Dockerfile中的下一步。

每个RUNADDCOPY指令本质上都是在一个新的容器中启动一个新的shell并执行一个命令。

 1 RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm" 2 RUN gem install rails 

可以读为

 1 Start a brand new shell Execute: source /usr/local/rvm/scripts/rvm Save the state of the file system as an image Exit shell 2 Start a brand new shell Execute: gem install rails ... 

当第1步完成时,shell(以及所有源于它的内容)消失。