В настоящее время у меня проблема с тестированием сборок образов Docker с помощью Serverspec. В двух словах, я хочу убедиться, что во время сборки образа кеш сборки Ruby gems очищается явно, например. выпустив rm -rf /usr/lib/ruby/gems/*/cache/*.gem
в Dockerfile.
Скелет 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/*
Перед добавлением команды удаления кеша гемов я реализовал следующий тест 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
Однако этого не должно быть, поскольку кеш гемов еще не очищен и, следовательно, не пуст, т.е. я ожидаю, что соответствующее утверждение не будет выполнено во время выполнения теста.
В этом легко убедиться, запустив контейнер из только что созданного образа и проверив каталог кеша 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()
по какой-то причине выполняются вне контейнера.