当前位置: 首页 > 知识库问答 >
问题:

使用 Serverspec 进行 Docker 映像构建测试时检查空的 Gem 缓存失败

薄欣怿
2023-03-14

我目前在通过Serverspec测试Docker映像构建时遇到了一个问题。简而言之,我想做的是确保在映像构建期间,Ruby gems构建缓存被明确清除,例如通过发出< code > RM-RF/usr/lib/Ruby/gems/*/cache/*。docker文件中的gem。

我正在处理的Dockerfile框架如下所示:

 # Dockerfile

 FROM alpine:3.7

 RUN apk add --no-cache \ 
     dumb-init \
     ruby \
  && apk add --no-cache --virtual .build-deps \
     build-base \
     ruby-dev

 RUN gem install --no-rdoc --no-ri json \
  && gem install --no-rdoc --no-ri oj

 RUN apk del .build-deps \
  && rm -rf /var/cache/apk/* \ 
     /tmp/* /var/tmp/*

在添加gem缓存删除命令之前,我实现了以下Serverspec测试,以便能够从失败的测试中启动:

 # ./spec/Dockerfile_spec.rb

 describe "Dockerfile" do
   before(:all) do
     @image = Docker::Image.build_from_dir('.')
     @image.tag(repo: 'demo', tag: 'latest')

     set :os, family: :alpine
     set :backend, :docker
     set :docker_image, @image.id
   end


   it "removes build dependencies during cleanup" do
     # Some more assertions 
     # ...
     expect(Dir.glob('/usr/lib/ruby/gems/*/cache/*.gem').size).to eq 0  
   end
 end

假设上面的Dockerfile文件,测试运行为绿色:

 $ bundle exec rspec spec/Dockerfile_spec.rb
 ....
 Finished in 3.95 seconds (files took 0.24091 seconds to load)
 4 examples, 0 failures

然而,情况不应该是这样的,因为gem缓存还没有被清空,因此不是空的,也就是说,我认为相应的断言在测试执行期间会失败。

这可以通过从新构建的映像启动容器并检查gems缓存目录来轻松验证:

 $ docker run --rm -it demo:latest sh
 / # ls /usr/lib/ruby/gems/2.4.0/cache/ 
 json-2.1.0.gem  oj-3.4.0.gem

反过来测试并期望一个非空目录,执行失败并显示一条错误消息:

 # ./spec/Dockerfile.rb

 it "removes build dependencies during cleanup" do
   # Some more assertions 
   # ...
   expect(Dir.glob('/usr/lib/ruby/gems/*/cache/*.gem').size).to_not eq 0  
 end


 # Command line 

 $ bundle exec rspec spec/Dockerfile_spec.rb
 .F..

 Failures:

   1) Dockerfile removes build dependencies during cleanup
      Failure/Error: expect(Dir.glob('/usr/lib/ruby/gems/*/cache/*.gem').size).to_not eq 0

      expected: value != 0
           got: 0

      (compared using ==)

显然,Dir。glob()命令未返回gems缓存目录中正确数量的文件。

有趣的是,在容器内手动运行Dir.glob()命令会返回预期的结果:

 $ docker run --rm -it demo:latest sh
 / # apk add --no-cache ruby-irb
 ...
 / # irb
 irb(main):001:0> Dir.glob('/usr/lib/ruby/gems/*/cache/*.gem').size
 => 2

首先,这让我认为测试没有在容器中正确执行,而是在主机上正确执行,但进一步的实验无法证实这一点。

你有什么想法吗?这可能是Serverspec/Rspec的问题吗?

谢谢!

首先,这让我认为测试没有在容器中正确执行,而是在主机上正确执行,但进一步的实验无法证实这一点。

我终于发现这个假设是错误的。实际上,Dir。glob()调用在容器外部执行,无论出于何种原因。

共有1个答案

皇甫雨石
2023-03-14

我终于知道哪里出了问题,实际上很简单:

让我们假设我们有一个像这样的Serverspec测试用例:

it "removes build dependencies during cleanup" do
  # Some more assertions 
  # ...
  expect(Dir.glob('/usr/lib/ruby/gems/*/cache/*.gem').size).to_not eq 0  
end

现在,在执行期间发生的事情是,在调用< code>expect()例程之前,先评估< code>Dir.glob()调用。因此,正如我在文章中已经指出的那样,< code>Dir.glob()命令在容器的作用域之外运行,而是检查相应的主机目录。如果您想检查容器文件夹是否为空,可以通过以下方式实现:

it "clears gem/apk caches as well as tmp files/dirs" do
  expect(command('ls /usr/lib/ruby/gems/*/cache/*.gem | wc -l').stdout).to eq "0\n"
end

诚然,这可能不是最美丽和优雅的解决方案,但基本上可以完成这项工作。如果你有其他想法和建议,请随时发布。

 类似资料:
  • 目前,我发现谷歌云构建发生在构建docker图像的时候(不像我想象的那样,它会构建我的图像,然后执行我的图像来完成所有的构建)。那是在这篇文章里 谷歌云构建的快速启动 我有一个Dockerfile现在很简单 我有一个单一的下载和提取下载任何工件(zip文件)从最后的单构建运行构建(只有修改的服务器被构建或依赖于上一个CI构建的变化的服务器被构建,就像下游库可能被更改)。第一行只是列出了我需要在一个

  • 我正在构建docker图像,但得到以下错误 有关更多详细帮助,请运行"ng[命令名]--help"致命错误:堆限制附近无效的标记-压缩分配失败-JavaScript堆内存溢出 [16:0x558f56668dc0] 212695 ms:标记-扫描971.6 (995.9)- ====JS堆栈跟踪 ========================================= 安全上下文:0x1

  • 当我使用docker-maven-plugin构建docker映像时,它失败了 错误:无法执行目标com.spotify:docker-maven-plugin:1.0.0:build(default-cli)on project spring-boot-basic:捕获异常:basedir/root/workspace/spring-boot-basic/spring-boot-basic/sp

  • 问题内容: 我尝试在构建映像的同时使用Docker安装软件,然后得到了。 我使用的Dockerfile 有没有一种方法可以在Dockerfile中运行docker命令来创建映像? 问题答案: 您的问题不在于Docker命令,因为它在错误消息中表示您的Docker守护程序未运行,或者由于某些配置问题而无法连接到它。 您刚刚安装了Docker吗?您是否完成了《安装指南》中的所有步骤? 您可以使用或来测

  • 我正在尝试基于ruby: 3.0构建Docker映像。在Dockerfile中,运行“RUN bundle install”时,开始安装依赖项,直到显示错误: Gem::Ext::BuildError:错误:未能生成Gem本机扩展#10 34.20 34.20当前目录:/usr/local/bundle/gems/tiny_tds-2.1.5/ext/tiny-tds#10 34.2/usr/lo

  • 我正试图用集装箱装一个样品。docker内的js应用程序。 我的docker文件如下,我在项目的工作目录中 我可以成功创建图像 无论如何,当我想运行应用程序时,它并不是一个正在运行的docker镜像 我不知道我哪里做错了? [PS:]根据评论,我已将CMD更改为 但是我不能构建镜像