zuazo / dockerspec

A small Ruby Gem to run RSpec and Serverspec, Infrataster and Capybara tests against Dockerfiles or Docker images easily.
https://rubygems.org/gems/dockerspec
Apache License 2.0
182 stars 9 forks source link

Cannot start bash at run - fail the test #10

Open wibimaster opened 7 years ago

wibimaster commented 7 years ago

Dockerspec Version

0.4.1

Ruby Version

ruby 2.3.4p301 (2017-03-30 revision 58214) [x86_64-linux]

Platform Details

Alpine Linux v3.4

Scenario

Try to build and test a Dockerfile with Node installed - the image does not start any service, so it's killed before the test can run

Steps to Reproduce

Create a Docker file with NodeJS installed and no CMD

Start a little test :

require 'dockerspec/serverspec'
describe 'My Dockerfile' do
  describe docker_build('../.') do
    it { should have_user 'nobody' }

    describe docker_run(described_image) do
      describe package('nodejs') do
        it { should be_installed }
      end
    end
  end
end

Expected Result

nodejs IS installed

Actual Result

Got an error because docker not running :

2) My Dockerfile Docker Build from path: "/projectfiles" Serverspec on tag: "94b3e9e391dc" Package "nodejs" should be installed Failure/Error: it { should be_installed } Docker::Error::NotFoundError: No such exec instance '27f4a7b4131e13343f0654fc2a3f38596209271e55cffa6c687aedd5e45a5823' found in daemon

So the real question is : How to start a bash in container to keep it alive when the test run ? (and kill all after ;))

zuazo commented 7 years ago

Hi @wibimaster,

Thanks for the report.

Can you add an example of the Dockerfile that fails, please.

wibimaster commented 7 years ago

Hi @zuazo ,

We can reproduce with this simple Dockerfile :

FROM ubuntu:16.04

ARG NODE_VERSION=7.9.0
ARG NPM_VERSION=4.5.0

# avoid error 'debconf: unable to initialize frontend: Dialog' on build
ARG DEBIAN_FRONTEND=noninteractive

# install NPM and cURL
RUN apt-get update --quiet --quiet && \
    apt-get install --quiet --yes wget npm && \
    rm --recursive --force /var/lib/apt/lists/*

# install Node
RUN npm install --loglevel=warn --global n && n $NODE_VERSION

CMD ["npm", "-v"]

As you can see, the default command is not a long-life service ; the objective is to "overlap" the default CMD to use "bash" with dockerspec, and have a long-life service started while the tests works...

For example, with arguments as second parameter : describe docker_run(described_image, 'bash') do

Is there any way to do this ?

Thanks !

zuazo commented 7 years ago

There could be different ways to do that.

What I usually do is create another Dockerfile with a long-running service that I only use for testing. See the following examples:

The process is:

  1. Create a Dockerfile in the spec/ directory that uses your root Dockerfile:
    ├─ Dockerfile
    └─ spec/
      ├─ mytests_spec.rb
      └─ Dockerfile

spec/Dockerfile example:

FROM mynpm
# long-life service:
CMD ["npm", "-v", "&&", "node"]
  1. In the *_spec.rb file, add a second docker_build call that builds your spec/Dockerfile after building your main Dockerfile.
require 'dockerspec/serverspec'
describe 'My Dockerfile' do
  describe docker_build('.', tag: 'mynpm') do
    # Make sure the CMD is correct, because it will be overwritten in the docker_run tests
    it { should have_cmd ["npm", "-v"] }
    # ...
    it { should have_user 'nobody' }

    # build the spec/Dockerfile:
    describe docker_build(File.dirname(__FILE__), tag: 'mynpm_test') do
      describe docker_run('mynpm_test') do
        # Add your running tests here  ...
      end
    end
  end
end

Maybe I should document this use case in the README. But, as I said, there could be other ways to do it.

Please, let me know if this does not solve your problem and I will reopen the issue.

wibimaster commented 7 years ago

Okay thanks, I understand the way you do it ; wish we could run the container with some specific arguments (like environnement variables, command), but seems to be not possible with actual docker testing technology :)