Ruby 的官方 Docker 镜像假设您只使用一个应用程序,一个 Gemfile,并且容器中不会安装或运行其他 gem 或 Ruby 应用程序。
如果您想在容器中安装多个 Gemfile,或者只是通过 RubyGems 安装 gem 并将其用作系统 gem,这种情况会很混乱,并且历史上会导致许多令人困惑的错误,这些错误似乎是 Bundler 中的错误。
但是,这些错误最终来自 Dockerfile 如何告诉 Bundler 在整个容器的单个全局位置创建 binstubs(与一个应用程序和 Gemfile 链接)。例如,如果您使用 rake
安装了两个 Gemfile,则运行 rake
命令将始终加载最后安装的 Gemfile,而不会加载其他任何 Gemfile。
要构建一个可以运行多个 Ruby 应用程序或使用 gem install
安装的全局命令的 Docker 容器,您需要更改 Ruby 官方 Docker 镜像中设置的默认值的一些环境变量。
在您的 Dockerfile 中,更改 PATH
和 GEM_HOME
,以便 Bundler 将所有 gem 安装到同一位置,并且运行命令将使用 RubyGems binstubs 而不是 Bundler 的应用程序锁定 binstubs。
ENV GEM_HOME="/usr/local/bundle"
ENV PATH $GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH
您还需要取消设置 BUNDLE_PATH
和 BUNDLE_BIN
。在 Docker 中取消设置环境变量可能有点棘手,但最常见的方法是在 ENTRYPOINT
脚本的开头。
#!/bin/bash
unset BUNDLE_PATH
unset BUNDLE_BIN
# your script goes here
完成此操作后,您将能够通过直接调用命令(如 rake
)来运行命令,而无需捆绑。您可以通过 cd
到该捆绑包的目录,然后使用 bundle exec
来在特定捆绑包中运行命令。例如,要在应用程序捆绑包中运行 rake,您将使用 bundle exec rake
。