Docker构建Rails镜像资产预编译提示未检测到Yarn如何解决
问题现象
使用Docker构建Rails应用镜像,其余流程正常,执行资产预编译步骤时抛出如下错误:
Yarn executable was not detected in the system.
原使用的Dockerfile配置如下:
FROM ruby:2.7.2 ENV RAILS_ROOT /var/www/quickcard ENV BUNDLE_VERSION 2.1.4 ENV BUNDLE_PATH usr/local/bundle/gems ENV RAILS_LOG_TO_STDOUT true ENV RAILS_PORT 5000 COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh RUN apt-get update -qq && apt-get install -y build-essential \ git \ libxml2-dev \ libpq-dev \ libxslt-dev \ nodejs \ yarn \ imagemagick \ tzdata \ less \ && rm -rf /var/cache/apk/* RUN gem install bundler --version "$BUNDLE_VERSION" RUN bundle config set path $BUNDLE_PATH RUN mkdir -p $RAILS_ROOT WORKDIR $RAILS_ROOT ADD Gemfile Gemfile ADD Gemfile.lock Gemfile.lock COPY yarn.lock yarn.lock RUN bundle install EXPOSE $RAILS_PORT RUN ln -s $RAILS_ROOT/config/systemd/puma.service /etc/systemd/system/quickcard COPY . . ENTRYPOINT ["entrypoint.sh"] RUN bundle exec rake assets:precompile CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
问题根因
报错核心是系统中安装的yarn并非前端依赖管理需要的Yarn程序:
- Debian默认apt软件源中名为
yarn的包是一款无关的命令行测试工具,和Rails资产编译需要的JS包管理器Yarn完全是两个软件,直接通过apt install yarn安装后系统无法识别到正确的Yarn命令。 - Dockerfile存在多处逻辑问题:
BUNDLE_PATH路径开头缺少斜杠属于相对路径、apt缓存清理命令用了Alpine发行版的路径不生效、提前复制yarn.lock却未执行JS依赖安装、容器内默认无systemd进程却添加了无效的systemd软链接配置,这些问题会进一步导致构建异常。
修复步骤
- 移除apt安装列表中的
yarn项,安装完Node.js后通过npm全局安装正版Yarn,避免装到同名错误包。 - 修正路径配置、apt缓存清理命令,移除无效的systemd软链接配置。
- 调整Dockerfile指令顺序:先安装所有系统、Ruby、JS依赖,再复制全量项目代码,最后执行资产预编译,同时合理利用Docker构建缓存减少重复构建耗时。
修正后的可正常运行的Dockerfile如下:
FROM ruby:2.7.2 ENV RAILS_ROOT /var/www/quickcard ENV BUNDLE_VERSION 2.1.4 # 修正路径为绝对路径 ENV BUNDLE_PATH /usr/local/bundle/gems ENV RAILS_LOG_TO_STDOUT true ENV RAILS_PORT 5000 ENV RAILS_ENV production COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh # 安装系统依赖,移除apt源中的错误yarn包 RUN apt-get update -qq && apt-get install -y build-essential \ git \ libxml2-dev \ libpq-dev \ libxslt-dev \ nodejs \ npm \ imagemagick \ tzdata \ less \ # 修正apt缓存清理路径为Debian系路径 && rm -rf /var/lib/apt/lists/* \ # 通过npm安装正确的Yarn包 && npm install -g yarn RUN gem install bundler --version "$BUNDLE_VERSION" RUN bundle config set path $BUNDLE_PATH RUN mkdir -p $RAILS_ROOT WORKDIR $RAILS_ROOT # 先复制依赖清单,利用构建缓存 ADD Gemfile Gemfile ADD Gemfile.lock Gemfile.lock COPY package.json yarn.lock ./ RUN bundle install # 提前安装JS依赖 RUN yarn install --frozen-lockfile EXPOSE $RAILS_PORT # 复制全量项目代码 COPY . . # 执行资产预编译 RUN bundle exec rake assets:precompile ENTRYPOINT ["entrypoint.sh"] CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
重新执行镜像构建命令,即可正常完成资产预编译流程,不会再触发Yarn不存在的报错。
内容的提问来源于stack exchange,提问作者Saad Saddique
相关产品推荐
相关产品推荐

