Rails Docker build 时遇到的 native extension 的问题

Catherine · 2021年09月13日 · 最后由 Catherine 回复于 2021年09月14日 · 400 次阅读

先放 Gemfile 和 Dockerfile

# Dockerfile
FROM ruby:3.0.0-alpine

ENV BUNDLER_VERSION=2.2.6

RUN apk --no-cache add postgresql-client \
  vim \
  yarn \
  wget \
  gcc \
  autoconf \
  libc-dev \
  linux-headers \
  make \
  libxml2-dev \
  libressl-dev \
  postgresql-dev \
  libffi-dev \
  readline-dev \
  yaml-dev \
  tzdata \
  git \
  nodejs \
  less \
  curl \
  g++ \
  ca-certificates \
  imagemagick \
  build-base \
  ruby-dev \
  libxslt-dev \
  libcurl

RUN gem install bundler -v 2.2.6

WORKDIR /app

COPY Gemfile Gemfile.lock ./

# Cuz it'd be extremely slow not doing so
RUN gem install sassc --version 2.4.0

RUN bundle config build.nokogiri --use-system-libraries

RUN bundle check || bundle install

COPY package.json yarn.lock ./

RUN yarn install --check-files

COPY . ./

# Gemfile
source "https://rubygems.org"

ruby '3.0.0'

gem 'rails', '~> 6.0.4'
gem 'puma', '~> 4.1'
gem 'sass-rails', '>= 6'
gem 'webpacker', '~> 4.0'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.7'
gem 'bootsnap', '>= 1.4.2', require: false

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'pry-rails'
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  gem 'webdrivers'
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

gem 'pg', '~>1.1.3'
gem 'sidekiq', '~>6.0.0'
gem "sidekiq-scheduler"
gem 'react-rails'

在本地 Mac 上打包,一切正常。但是在 ubuntu 的 vps (1G/1C) 上,执行到 bundle install 时,会在 sassc 2.4.0 的 build native extensions 那一步卡的非常非常久。并且 CPU 和内存在这一步的时间段里,基本上占用都是 80% 左右。

但独执行写一行 RUN 来安装 sassc,可以解决这个问题,也可以拿 Mac 上打包好的作为个基础 image 解决问题。

但我有一个问题不太明白。 bundle install 和 gem install 无非是一个用 bundle 来负责安装。bundle 在安装的版本上会做出最兼容的选择,比如 A 和 B 都需要 sassc 的依赖的情况下。但我已经在 Gemfile 中明确指明 2.4 版本,依然在 ubuntu 中失败。既然和版本没关系,为什么:

  1. Mac 中 build 到 bundle 那一步安装 sassc 直接就过了,内存和 CPU 强一点的原因?
  2. 单独加一层 RUN 去用 gem 直接安装 sassc 就成功了。而放在 Dockerfile 中让 bundle 去安装却卡死了,为什么会有这个区别?

我觉得就是 cpu 和内存太小,以前不用 docker 我也碰到过过 1 G 内存在编译 gem 的时候卡死。

构建镜像的机器性能要好一点,生产环境资源少就不要放在生产环境编译了。编译好 push 到 registry,然后生产环境拉镜像。

1c1g 出现这种情况很正常。。。。

先提交 Gemfile.lock 可以利用构建缓存。要不然每次部署都安装就很累。

pynix 回复

恩,是的。我的问题应该就是 Rei 说的内存太小了。因为我的机子里还挂了一个被 sidekiq 持续修改的文件,以及代理这个文件做显示的 nginx。实际闲置内存可能还少了两三百 MB...巧妇难为无米之炊,钱没给够还让 docker 打包,是有点黑了 哈哈

Catherine 回复

本地打。。。

Catherine 回复

我用 API mode 好像不需要依赖这个。。。

pynix 回复

它是个整合以及压缩 scss 和 sass 的工具,API 模式不存在这些静态资源,自然也就没有了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号