Skip to content

Instantly share code, notes, and snippets.

@masonforest
Last active March 18, 2020 16:34
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save masonforest/194e0cb6bb16c88e21a0 to your computer and use it in GitHub Desktop.
Save masonforest/194e0cb6bb16c88e21a0 to your computer and use it in GitHub Desktop.
Test Drive Your Dockerfiles with RSpec and ServerSpec
FROM ubuntu:14.04
MAINTAINER Mason Fischer <mason@thoughtbot.com>
RUN apt-get update && apt-get install -y nodejs
require "serverspec"
require "docker"
describe "Dockerfile" do
image = Docker::Image.build_from_dir('.')
set :os, family: :debian
set :backend, :docker
set :docker_image, image.id
it "installs the right version of Ubuntu" do
expect(os_version).to include("Ubuntu 14")
end
it "installs required packages" do
expect(package("nodejs")).to be_installed
end
def os_version
command("lsb_release -a").stdout
end
end
@kgrvamsi
Copy link

Hello,

I get this error

Dockerfile
installs the right version of Ubuntu (FAILED - 1)

Failures:

  1. Dockerfile installs the right version of Ubuntu
    Failure/Error: command("lsb_release -a").stdout
    NoMethodError:
    undefined method `stdout' for #Docker::Container:0x0000000212b3d8
 # /var/lib/gems/1.9.1/gems/serverspec-2.7.1/lib/serverspec/type/command.rb:4:in `stdout'
 # ./spec/EMS/Dockerfile_spec.rb:19:in `os_version'
 # ./spec/EMS/Dockerfile_spec.rb:15:in `block (2 levels) in <top (required)>'

Finished in 0.36045 seconds (files took 0.8135 seconds to load)
1 example, 1 failure

And i would like to know the serverspec and ruby version you are using ?

Thanks,
Vamsi KGR

@dekz
Copy link

dekz commented Feb 26, 2015

yo Vamsi you want to take a look over at my comment here.

Basically, you've got a newer version of specinfra which has a 'fix' for Containers with nil CMD. What that fix is actually doing is replacing your Dockerfile CMD and misusing an shell expression. This blows up, you end up getting the wrong object returned which doesn't give you an object with #stdout.

I'd recommend just watching that issue and see what happens, in the meantime, downgrade your serverspec and specinfra.

@kgrvamsi
Copy link

Hi @dekz,

Thanks for your reply.Can you recommend me the version to use for serverspec and specinfra.it will be great help so that i can see if this sort issue occurs again in my env

Thanks,
Vamsi KGR

@arioch
Copy link

arioch commented Feb 27, 2015

Hm. I'm getting this error:

Failures:

  1) Dockerfile installs required packages
     Failure/Error: expect(package('ruby')).to be_installed
       expected Package "ruby" to be installed

     # ./spec/Dockerfile_spec.rb:25:in `block (2 levels) in <top (required)>'

  2) Dockerfile Package "ruby" should be installed
     Failure/Error: it { should be_installed }
       expected Package "ruby" to be installed

     # ./spec/Dockerfile_spec.rb:29:in `block (3 levels) in <top (required)>'

Finished in 1.68 seconds (files took 0.28967 seconds to load)
3 examples, 2 failures

Which is weird because it really is installed.

@dekz
Copy link

dekz commented Feb 27, 2015

arioch to be honest I haven't had a look at how the internal of serverspecs works with regards to checking packages installed. But since yours is up and running unlike Vamsi's then I'd suggest digging in a bit further.

Vamsi, try v2.15.0 of specinfra. v2.15.1 is the release is the buggy release. Or try applying my commit here.

@cptactionhank
Copy link

I didn't have any success getting this to work using latest serverspec and specinfra 2.15.0, 2.15.1, 2.15.2, nor 2.16.0 does a full example "project" exist, where i could just go git clone ... and rake spec?

@kgrvamsi
Copy link

kgrvamsi commented Mar 2, 2015

I wonder if the problem is their in my setup or with the above spec file 😔

Here is what some thing i get after the specinfra v2.15.0 installed

 1) Dockerfile installs the right version of Ubuntu
     Failure/Error: command("lsb_release -a").stdout
     NoMethodError:
       undefined method `stdout' for #<Docker::Container:0x00000002541b20>

Here are some of my machine details


root@vagrant:/vagrant# ruby -v
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
root@vagrant:/vagrant# docker version
Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.4.1
Git commit (client): a8a31ef
OS/Arch (client): linux/amd64
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.4.1
Git commit (server): a8a31ef

root@vagrant:/vagrant# gem list

*** LOCAL GEMS ***

archive-tar-minitar (0.5.2)
bundle (0.0.1)
bundler (1.8.2)
diff-lcs (1.2.5)
docker-api (1.19.0)
excon (0.44.2)
json (1.8.2)
multi_json (1.10.1)
net-scp (1.2.1)
net-ssh (2.9.2)
rspec (3.2.0)
rspec-core (3.2.0)
rspec-expectations (3.2.0)
rspec-its (1.2.0)
rspec-mocks (3.2.0)
rspec-support (3.2.1)
serverspec (2.7.1)
specinfra (2.15.0)

Btw the commit is more specific to the CMD inside the Dockerfile to check or with the cmd to execute in the spec file?
This really halts my work so badly 😫 #dekz or @dekz need you help on this

@tfhartmann
Copy link

@masonforest great blog post! Any suggestions on how to go about removing the images after the tests get run? I've tried it this way, but this doesn't seem right (or to work!)

https://github.com/tfhartmann/docker-puppetserver/blob/73935b2a3aaedca27e3c0984823912b565f39546/spec/Dockerfile_spec.rb#L14-L16

@cjcjameson
Copy link

Just calling out: it's important to specify that you should use the docker-api gem. The docker gem is not the right one to use. But confusingly, the require statement is correct!
require "docker"

@bossjones
Copy link

@cjcjameson you just saved me a lot of time buddy, thx. and thx @masonforest !

@josefsalyer
Copy link

Oh my! The docker-api gem! what a difference that makes! @masonforest - do you think you can update the article to call this out? it would have saved me a bunch of time!

@josefsalyer
Copy link

@tfhartmann : I add this to my specs:

after(:all) do
    @image.remove(:force => true)
end

@jrglee
Copy link

jrglee commented Apr 8, 2016

In the example you build the image only. I assume ServerSpec is starting the container and stopping by the end of the test. How can you pass arguments to the container such as environment variables, commands, volumes, etc?

@irvifa
Copy link

irvifa commented May 30, 2016

Hello, this is my version of docker:

$ docker -v                                                                     
Docker version 1.11.1

I can't using rspec and always getting this message:

$ bundle exec rspec spec                                             
No examples found.


Finished in 0.00098 seconds (files took 1.23 seconds to load)
0 examples, 0 failures

this is my directory structure:

$ tree .                                                                          ‹ruby-2.3.0›
.
├── Dockerfile
├── run
└── spec
    └── Dockerfile_spec.rb

1 directory, 3 files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment