使用 Docker 镜像运行 bundle install 会忽略 bundle config 设置

Posted

技术标签:

【中文标题】使用 Docker 镜像运行 bundle install 会忽略 bundle config 设置【英文标题】:Using a Docker image to run bundle install ignores bundle config setting 【发布时间】:2022-01-19 17:03:37 【问题描述】:

我希望使用 Docker 映像 (ruby:3.0) 构建映像,而无需(最终)在本地安装 Ruby。

出于测试目的,我在 Windows 10 WSL2 环境中安装了 Ruby 2.7.0:

$ ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux-gnu]

我有一个Gemfile

来源“https://rubygems.org”

gem 'sinatra'

group :development, :test do
    gem 'thin'
    gem 'sqlite3'
end

并且捆绑器设置为在项目目录中安装 Gems:

$ cat .bundle/config
---
BUNDLE_PATH: "vendor/bundle"

如果我在本地运行bundle install

$ bundle install
Fetching gem metadata from https://rubygems.org/...
Resolving dependencies...
Using bundler 2.2.17
Fetching rack 2.2.3
Fetching tilt 2.0.10
Fetching daemons 1.4.1
Fetching sqlite3 1.4.2
Fetching eventmachine 1.2.7
Fetching ruby2_keywords 0.0.5
Installing rack 2.2.3
Installing tilt 2.0.10
Installing sqlite3 1.4.2 with native extensions
Installing ruby2_keywords 0.0.5
Installing daemons 1.4.1
Installing eventmachine 1.2.7 with native extensions
Fetching mustermann 1.1.1
Installing mustermann 1.1.1
Fetching rack-protection 2.1.0
Installing rack-protection 2.1.0
Fetching sinatra 2.1.0
Installing sinatra 2.1.0
Fetching thin 1.8.1
Installing thin 1.8.1 with native extensions
Bundle complete! 3 Gemfile dependencies, 11 gems now installed.
Bundled gems are installed into `./vendor/bundle`

Gem 安装到 ./vendor/bundle 目录:

确认:

$ bundle info thin
  * thin (1.8.1)
        Summary: A thin and fast web server
        Homepage: https://github.com/macournoyer/thin
        Source Code: https://github.com/macournoyer/thin
        Changelog: https://github.com/macournoyer/thin/blob/master/CHANGELOG
        Path: /home/craig/ruby/dev/vendor/bundle/ruby/2.7.0/gems/thin-1.8.1

接下来,我使用ruby:3.0 图像将 Gems 捆绑到项目目录中。

我删除了Gemfile.lock./vendor/bundle 目录,然后使用图像运行bundle install

$ docker run --rm -v "$(pwd)":/src -w /src ruby:3.0 bundle install
Fetching gem metadata from https://rubygems.org/...
Resolving dependencies...
Using bundler 2.2.32
Fetching sqlite3 1.4.2
Fetching eventmachine 1.2.7
Fetching rack 2.2.3
Fetching tilt 2.0.10
Fetching ruby2_keywords 0.0.5
Fetching daemons 1.4.1
Installing ruby2_keywords 0.0.5
Installing tilt 2.0.10
Installing daemons 1.4.1
Installing sqlite3 1.4.2 with native extensions
Installing rack 2.2.3
Fetching mustermann 1.1.1
Installing eventmachine 1.2.7 with native extensions
Installing mustermann 1.1.1
Fetching rack-protection 2.1.0
Installing rack-protection 2.1.0
Fetching sinatra 2.1.0
Installing sinatra 2.1.0
Fetching thin 1.8.1
Installing thin 1.8.1 with native extensions
Bundle complete! 3 Gemfile dependencies, 11 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

这个过程似乎安装了 Gems,但没有安装到 ./vendor/bundle。尝试识别位置会产生错误:

$ bundle info thin
Could not find daemons-1.4.1 in any of the sources

.bundle/config 似乎被忽略了。我猜 Gems 实际上是安装到为运行 bundle install 而创建的容器中。

有没有办法让它使用.bundle/config

【问题讨论】:

【参考方案1】:

发生这种情况的原因有几个:

    gem安装目录,在打包镜像的bundler配置中配置 BUNDLE_APP_CONFIG docker 镜像中定义的环境变量

查看捆绑器文档,我们必须注意以下几点:

    list of available keys、BUNDLE_PATH 不存在,但path 是...

安装指定 gem 的位置。

    executing config

执行bundle config set --local <name> <value> 将在本地应用程序的目录中设置该配置。配置将存储在<project_root>/.bundle/config。如果设置了BUNDLE_APP_CONFIG,配置会保存在$BUNDLE_APP_CONFIG/config

    Bundler 按此顺序加载配置设置

本地配置 (<project_root>/.bundle/config ...)

让我们试一试...

$ docker run --rm -it -v $PWD:/src --workdir /src --entrypoint /bin/sh ruby:alpine

/src # ls -l
total 0

/src # echo $BUNDLE_APP_CONFIG
/usr/local/bundle

/src # export BUNDLE_APP_CONFIG=$PWD/.bundler

$ bundle config set --local path 'vendor/bundle'
/src # ls -la
total 4
drwxr-xr-x    3 root     root            96 Dec 16 21:10 .
drwxr-xr-x    1 root     root          4096 Dec 16 21:10 ..
drwxr-xr-x    3 root     root            96 Dec 16 21:10 .bundler

/src # bundle config
Settings are listed in order of priority. The top value will be used.
app_config
Set via BUNDLE_APP_CONFIG: "/src/.bundler"

path
Set for your local app (/src/.bundler/config): "vendor/bundle"

silence_root_warning
Set via BUNDLE_SILENCE_ROOT_WARNING: true

/src # bundle init
Writing new Gemfile to /src/Gemfile

/src # echo 'gem "sinatra"' >> Gemfile

/src # bundle install --quiet

/src # ls -l
total 8
-rw-r--r--    1 root     root           161 Dec 16 21:12 Gemfile
-rw-r--r--    1 root     root           398 Dec 16 21:13 Gemfile.lock
drwxr-xr-x    3 root     root            96 Dec 16 21:18 vendor

/src # du -sh vendor/bundle/
3.1M    vendor/bundle/

/src # bundle exec rackup --version
Rack 1.3 (Release: 2.2.3)

/src # exit

$ ls -ax1
.
..
.bundler
Gemfile
Gemfile.lock
vendor

如你所见:

    bundle 的配置保存在你的本地目录中 捆绑器将 gem 安装到您的本地目录中

【讨论】:

以上是关于使用 Docker 镜像运行 bundle install 会忽略 bundle config 设置的主要内容,如果未能解决你的问题,请参考以下文章

Docker-in-Docker 与 Gitlab 共享运行器,用于构建和推送 docker 镜像到注册表

[docker]使用 crun 本地跑container

.Net Core in Docker - 使用阿里云Codepipeline及阿里云容器镜像服务实现持续集成(CI)

4.3 runner里的docker-in-docker

如何在Openshift平台上通过Jenkins管道运行docker-in-docker?

Kubernetes In Action :2开始使用Kubernetes和Docker