构建简易Rails应用失败:rake等命令无法找到
Rails Docker构建与启动报错排查解决方案
问题概述
拉取极简Rails应用并修改后本地运行正常,但Docker构建时执行bundle exec rake assets:precompile报错找不到rake;注释该命令构建成功后,启动容器仍报rake缺失、无法加载rails组件;切换为Passenger启动后,又出现rack依赖缺失的错误。
关键报错信息
- rake缺失报错:
bundler: failed to load command: rake (/minirails/vendor/bundle/ruby/2.7.0/bin/rake) Gem::Exception: can't find executable rake for gem rake. rake is not currently included in the bundle, perhaps you meant to add it to your Gemfile? - Passenger启动报错:
App 97 output: Error: The application encountered the following error: cannot load such file -- rack (LoadError)
现有配置文件片段
Gemfile:
source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.7.6' gem 'rails', '~> 6.1' gem 'sqlite3', '~> 1.4' gem 'puma', '~> 4.1' gem 'sass-rails', '>= 6' group :development, :test do gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end group :development do gem 'listen', '~> 3.2' end
Dockerfile核心步骤:
ADD Gemfile Gemfile.lock /minirails/ WORKDIR minirails COPY ./ /minirails RUN bundle config set deployment 'true' RUN bundle config set without 'development test' RUN bundle install
问题根源
- 核心依赖缺失:Rails 6.x中rake默认属于
development组依赖,Docker构建时通过without 'development test'排除了该组,导致production环境未安装rake;rack作为Rails核心依赖,若Gemfile.lock未包含production环境的完整依赖,也会出现缺失。 - 构建顺序不合理:先添加Gemfile再复制整个项目,可能覆盖Gemfile/Gemfile.lock,且未利用Docker缓存,导致依赖安装基于不匹配的配置。
- 启动脚本环境不兼容:原脚本未正确加载bundle环境,Passenger启动时未关联bundle安装的gem。
修复步骤
1. 调整Gemfile,确保核心依赖全局可用
在Gemfile中显式添加rake到全局(非分组),确保production环境能安装:
source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.7.6' gem 'rails', '~> 6.1' gem 'sqlite3', '~> 1.4' gem 'puma', '~> 4.1' gem 'sass-rails', '>= 6' gem 'rake' # 显式添加,确保production环境安装 group :development, :test do gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end group :development do gem 'listen', '~> 3.2' end
本地执行bundle install更新Gemfile.lock,确保rake被纳入依赖列表。
2. 优化Docker构建流程
修改Dockerfile的文件复制顺序,优先处理Gemfile以利用缓存,避免文件覆盖:
FROM ruby:2.7.6-bullseye LABEL maintainer="Me" EXPOSE 3000 ENTRYPOINT ["/docker-entrypoint.sh"] ENV PATH=/root/.yarn/bin:$PATH RAILS_ENV=production SECRET_KEY_BASE=c1f89d98........d47bc66fdcd417 ENV TZ=Europe/Berlin # 合并系统依赖安装命令,减少分层 RUN apt-get update && apt-get upgrade -y && \ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7 && \ apt-get install -y apt-transport-https ca-certificates && \ sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bullseye main > /etc/apt/sources.list.d/passenger.list' && \ apt-get update && apt-get install -y nginx-extras passenger curl certbot python3-certbot-nginx yarn nano cron tzdata && \ ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone WORKDIR /minirails # 先复制Gemfile相关文件,利用Docker缓存 COPY Gemfile Gemfile.lock ./ # 配置bundle并安装依赖 RUN bundle config --global silence_root_warning 1 && \ bundle config set deployment 'true' && \ bundle config set without 'development test' && \ bundle install # 复制项目其余文件 COPY ./ ./ RUN mkdir -p vendor RUN echo "Rails.application.config.app_version = '$(date +%d.%m.%Y)'" > ./config/initializers/version.rb # 取消注释预编译命令,此时rake已安装 RUN bundle exec rake assets:precompile ADD ./docker-entrypoint.sh /
3. 修复启动脚本
修改docker-entrypoint.sh,确保bundle环境正确加载,推荐使用Rails默认的Puma服务器:
#!/usr/bin/env bash set -e # 执行数据库迁移 bundle exec rake db:migrate # 启动Rails服务器,绑定0.0.0.0以支持外部访问 bundle exec rails server -b 0.0.0.0 -p 3000
若坚持使用Passenger,需添加--bundle-exec参数关联bundle依赖:
#!/usr/bin/env bash set -e bundle exec rake db:migrate passenger start --port 3000 --environment production --bundle-exec
4. 调试验证
- 构建时添加
RUN bundle list命令,查看已安装的gem,确认rake、rack、rails等核心组件存在; - 启动容器前进入调试模式:
在容器内执行docker run -it --entrypoint bash minirailsbundle exec rake -v验证rake可用性,bundle exec rails -v验证rails命令是否正常。
内容的提问来源于stack exchange,提问作者MDickten
相关产品推荐
相关产品推荐

