使用Serverspec进行Docker映像构建测试时,检查空的缓存失败 [英] Checking on empty gems cache fails using Serverspec for Docker image build testing

查看:215
本文介绍了使用Serverspec进行Docker映像构建测试时,检查空的缓存失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在通过Serverspec测试Docker镜像版本时遇到了问题。简而言之,我想要做的是确保在图像构建期间,Ruby gems构建缓存被显式清除,例如,通过在Dockerfile中发布 rm -rf / usr / lib / ruby​​ / gems / * / cache / *。gem



我正在使用的Dockerfile框架如下所示:

 #Dockerfile 

FROM alpine:3.7

RUN apk添加--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 cache删除命令之前,我实现了以下Serverspec测试,以便能够从失败的测试中启动:

 #./spec/Dockerfile_spec.rb 

描述Dockerfile在执行之前执行

@image = Docker :: Image.build_from_dir(' ')
@ image.tag(回购:'demo',标记:'latest')

设置:os,family::alpine
设置:后端,:docker
set:docker_image,@ image.id
结束


它在清理期间删除构建依赖关系do
#更多断言
#...
expect(Dir.glob('/ usr / lib / ruby​​ / gems / * / cache / *。gem')。size).to eq 0
end
end

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

  $ bundle exec rspec spec / Dockerfile_spec.rb 
....
完成于3.95秒(文件花费0.24091秒)
4个例子,0个故障

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



这可以通过从新建图像启动容器并检查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

测试另一种方式并期待非-empty目录,执行失败,并显示错误消息:

 #./spec/Dockerfile.rb 

it在清理期间删除构建依赖关系do
#更多断言
#...
expect(Dir.glob('/ usr / lib / ruby​​ / gems / * / cache /*.gem').size).to_not eq 0
end


#命令行

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

失败:

1)Dockerfile在清理过程中移除构建依赖关系
失败/错误:expect(Dir.glob('/ usr / lib / ruby​​ / gems / * / cache / *。gem')。size).to_not eq 0

expected :value!= 0
got:0

(使用==比较)

显然, 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的问题吗?



Thx!

编辑




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


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

解决方案

我终于明白出了什么问题,其实很简单:
$ b $假设我们有一个这样的Serverspec测试用例:

 它在清理过程中删除构建依赖关系做
#更多的断言
#...
expect(Dir.glob('/ usr / lib / ruby​​ / gems / * / cache / *。gem')。size)。 to_not eq 0
end

现在执行过程中发生的是在调用 expect()例程之前计算Dir.glob()调用。因此,正如我在文章中已经指出的那样, Dir.glob()命令在容器范围之外运行,并且检查相应的主机目录。
如果你想检查一个容器文件夹是否为空,你可以如下实现:

 它清除gem / apk缓存以及tmp文件/目录do 
expect(命令('ls /usr/lib/ruby/gems/*/cache/*.gem | wc -l')。stdout ).to eq0 \\\

end

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

I'm currently having an issue with testing Docker image builds by means of Serverspec. In a nutshell, what I want to do is ensuring that during the image build the Ruby gems build cache gets cleared explicitly, e.g. by issuing rm -rf /usr/lib/ruby/gems/*/cache/*.gem in the Dockerfile.

The Dockerfile skeleton I'm working with looks like this:

 # 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/*

Before adding the gem cache removal command, I implemented the following Serverspec test to be able to start from a failing test:

 # ./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

Assuming the Dockerfile from above, the tests run green:

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

However, this should not be the case since the gem cache has not yet been cleared and thus is not empty, i.e. I'd expect the corresponding assertion to fail during test execution.

This can easily be verified by launching a container from the freshly built image and checking the gems cache directory:

 $ 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

Testing the other way around and expecting a non-empty directory, the execution fails with an error message:

 # ./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 ==)

So obviously, the Dir.glob() command does not return the correct number of files in the gems cache directory.

Funny enough, running the Dir.glob() command manually inside the container returns the expected result:

 $ 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

First, this made me think that the test is not properly executed within the container but on the host instead, but further experiments could not confirm this.

You have any ideas? Could this be a Serverspec/Rspec issue?

Thx!

Edit

First, this made me think that the test is not properly executed within the container but on the host instead, but further experiments could not confirm this.

I finally found out that this assumption was wrong. Actually, the Dir.glob() calls are executed outside the container, for whatever reason.

解决方案

I finally figured out what went wrong, and actually it's pretty simple:

Let's assume that we have a single Serverspec test case like this one:

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

Now what's happening during execution is that the Dir.glob() call is evaluated before the expect() routine is invoked. Consequently, as I already pointed out in my post, the Dir.glob() command is run outside of the container's scope and checks the corresponding host directory instead. If you ever want to check if a container folder is empty or not, you can achieve this as follows:

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

Admittedly, this is probably not the most beautiful and elegant solution but basically does the job. If you have other ideas and proposals, feel free to post them.

这篇关于使用Serverspec进行Docker映像构建测试时,检查空的缓存失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆