TL;DR: I can't delete my Docker image from inside my RSpec script, because RSpec still has a dependent container
I'm using RSpec to test my Dockerfiles. That is, to test whether the Dockerfile results in a correct image. My test script does this by building an image from the Dockerfile, and then letting RSpec test whether a container (based on that image) has the correct contents.
The execution flow is as follows:
- My RSpec script builds the Docker image (in its
before(:all)
block) - Serverspec creates a Docker container (based off the Docker image)
- RSpec / Serverspec executes the tests inside the Docker container
- RSpec / Serverspec calls my RSpec script's
after(:all)
block - RSpec / Serverspec deletes the Docker container
I tried to delete the image from inside the after(:all)
block (or the after(:context)
block, but that has the same issue), as that is the last hook that RSpec offers me. Only I can't, because the Docker container has not been deleted yet.
Force-deletion is no solution, as Docker then keeps an unnamed, untagged version of the image around.
Is there an (idiomatic) way to accomplish this?
Example RSpec script:
require "serverspec"
require "docker-api"
describe "Dockerfile" do
image_name = 'my_image'
image_tag = 'my_tag'
image_name_tag = image_name + ':' + image_tag
before(:all) do
set :os, family: :debian
set :backend, :docker
# Build image
@image = Docker::Image.build_from_dir("../dockerfile/")
@image.tag(repo: image_name, tag: image_tag)
# Provide Serverspec with our image's id
set :docker_image, @image.id
end
it "is a Debian-based container" do
expect(os_version).to include("Debian")
end
def os_version
command("cat /etc/*release").stdout
end
after(:context) do
# Clean up
@image.delete(name: image_name_tag) # <-- this fails
end
end
(It's not entirely clear to me where RSpec's responsibilities end and Serverspec's begin; hence the RSpec / Serverspec above.)