Ruby 的官方 Docker 映像假設您只會使用一個應用程式,搭配一個 Gemfile,而且不會在您的容器中安裝或執行其他寶石或 Ruby 應用程式。
如果您想在容器中安裝多個 Gemfile,或只是透過 RubyGems 安裝寶石並將它們用作系統寶石,這種情況會令人困惑,而且歷來導致許多令人困惑的錯誤,這些錯誤看起來像是 Bundler 中的錯誤。
然而,這些錯誤最終來自於 Dockerfile 告訴 Bundler 在整個容器中建立 binstub(連結至一個應用程式和 Gemfile)的單一全域位置的方式。例如,如果您使用 rake
安裝兩個 Gemfile,執行 rake
指令時,它將永遠載入最後安裝的 Gemfile,而不會載入任何其他 Gemfile。
若要建立一個可以執行多個 Ruby 應用程式或使用 gem install
安裝的全域指令的 Docker 容器,您需要變更 Ruby 官方 Docker 映像中設定的預設值中的一些環境變數。
在您的 Dockerfile 中,變更 PATH
和 GEM_HOME
,讓 Bundler 將所有寶石安裝到相同的位置,而且執行指令時將使用 RubyGems binstub,而不是 Bundler 的應用程式鎖定的 binstub
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
完成後,您將能夠直接呼叫指令來執行它們,而不需要 bundle,例如 rake
。您可以透過 cd
到該 bundle 的目錄,然後使用 bundle exec
來執行特定 bundle 中的指令。例如,若要在應用程式 bundle 內執行 rake,您會使用 bundle exec rake
。