如何在Docker中无需显式执行/bin/bash即可正常使用RVM?
解决Heroku-20环境下Ruby依赖需手动调用bash的问题
修改后的完整Dockerfile
# 使用官方Heroku-20镜像作为基础 FROM heroku/heroku:20 # 全局设置默认shell为登录模式bash,后续所有RUN自动用这个环境执行命令 SHELL ["/bin/bash", "-l", "-c"] WORKDIR /app # 定义要安装的Ruby版本 ENV RUBY_VERSION 2.7.5 # 安装系统依赖包 RUN apt-get update && \ apt-get install -y build-essential libpq-dev nodejs curl gpg && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* # 安装RVM并配置指定Ruby版本 RUN gpg --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB && \ curl -sSL https://get.rvm.io | bash -s stable && \ rvm requirements && \ rvm install $RUBY_VERSION && \ rvm use $RUBY_VERSION --default # 安装指定版本的Bundler RUN gem install bundler -v '2.3.6' --no-document # 先复制Gemfile相关文件,利用Docker缓存优化构建速度 COPY Gemfile Gemfile.lock ./ # 复制整个应用代码 COPY . . # 验证Ruby环境是否正常 RUN which ruby && ruby -v && rvm list # 安装Gem依赖 RUN bundle install # 容器启动默认进入登录模式bash CMD ["/bin/bash", "-l"]
核心修改点
- 全局配置登录shell:在镜像开头添加
SHELL ["/bin/bash", "-l", "-c"],让所有后续RUN命令自动在登录模式bash下执行。RVM的环境变量只有登录shell才会自动加载/etc/profile.d/rvm.sh,这样直接调用rvm、ruby这些命令就不会找不到了,不用每次手动加/bin/bash -l -c前缀。 - 简化命令写法:所有原本需要包裹在
/bin/bash -l -c里的命令,现在直接写即可,比如rvm install $RUBY_VERSION、bundle install。 - 缓存优化:先复制Gemfile和Gemfile.lock,再复制其他代码,这样Gem依赖安装层可以复用缓存,不用每次改代码都重新装gem。
可选优化
如果不想依赖登录shell,也可以直接把Ruby的可执行文件路径加入系统PATH:
# 在安装完Ruby后添加这条ENV指令 ENV PATH "/root/.rvm/rubies/ruby-${RUBY_VERSION}/bin:$PATH"
这样即使在非登录shell下,系统也能找到ruby、gem、bundle这些命令,兼容性更强。
内容的提问来源于stack exchange,提问作者Kamilski81
相关产品推荐
相关产品推荐

