Last Updated: February 25, 2016
·
6.036K
· tcnksm

TDD for Dockerfile by RSpec (severspec)

I wrote some Dockerfiles. Now Dockerfile I made is very simple but I may be restless when Dockerfile become longer and more complex. To remove such anxiety, we should write TEST for it. If we can build Dockerfile with TDD process, it is great !

There is great post about TDD for Dockerfile, "Experimenting with test driven development for docker" by PIETER JOOST VAN DE SANDE. He tried to test Dockerfile by Docker API. It is nice but it can not test about confirming package installation. I tried it with serverspec by Gosuke Miyashita.

tcnksm/docker-rspec

With serverspec, you can write RSpec tests for checking your severs are configured correctly or not. It is used with configuration management tool like Pupet or Chef. I applied it to testing Dockerfile.

Preparation (ssh and sudoer)

To use serverspec, we need to prepare ssh login user to docker container and sudoer. Prepare below Dockerfile to meet these conditions.

FROM ubuntu

# Install ssh
RUN apt-get update
RUN apt-get install -y openssh-server

# Setting ssh
RUN mkdir /var/run/sshd
RUN /usr/sbin/sshd
CMD ["/usr/sbin/sshd", "-D"]

# Create user and set sudo password
RUN useradd tcnksm
RUN echo tcnksm:**** | chpasswd

# Setting ssh login without sudo
RUN mkdir -p /home/tcnksm/.ssh
RUN chown tcnksm /home/tcnksm/.ssh
RUN chmod 700 /home/tcnksm/.ssh
ADD ./id_rsa.pub /home/tcnksm/.ssh/authorized_keys
RUN chown tcnksm /home/tcnksm/.ssh/authorized_keys
RUN chmod 700 /home/tcnksm/.ssh/authorized_keys

# Setting sudoers
RUN echo "tcnksm   ALL=(ALL)   ALL" > /etc/sudoers.d/tcnksm

You can add your pass word at **** and change name tcnksm to your name. And you need to prepare your id_rsa.pub in current directory.

Build image and run container.

$ docker build -t tcnksm/sample .
$ docker run -p :22 -d tcnksm/sample /usr/sbin/sshd -D

Preparation (serverspec)

Installation of serverspec

$ gem install 'serverspec'

After installation, configure it.

$ serverspec-init
Select OS type:

  1) UN*X
  2) Windows

Select number: 1

Select a backend type:

  1) SSH
  2) Exec (local)

Select number: 1

Vagrant instance y/n: n
Input target host name: 192.168.50.4

I assume docker is run on 192.168.50.4 host.

Now spec_helper.rb and sample rspec test are generated. In this case, use default spec_helper.rb.

Set up ~/.ssh/config

Host 192.168.50.4
   HostName 192.168.50.4
   User tcnksm
   Port 7654
   UserKnownHostsFile /dev/null
   StrictHostKeyChecking no
   PasswordAuthentication no
   IdentityFile /Users/tcnksm/.ssh/id_rsa
   IdentitiesOnly yes
   LogLevel FATAL

You should change tcnksm to your ssh user name.

And set up environmental variable of sudoer password on docker container you added in Dockerfile.

$ export SUDO_PASSWORD="****"

Write Test

Now setup is done. Let's write test. For example, write test confirming git command is installed.

# spec/192.168.50.4/git_spec.rb
require 'spec_helper'

describe package('git') do
  it { should be_installed }
end

Run test (Red)

Test will be failed because git is not installed on docekr container.

$ rspec
F

Failures:

  1) Package "git" should be installed
       Failure/Error: it { should be_installed }
              sudo dpkg-query -f '${Status}' -W git | grep '^install ok installed$'

dpkg-query: no packages found matching git
       expected Package "git" to be installed
            # ./spec/192.168.50.4/git_spec.rb:4:in `block (2 levels) in <top (required)>'

Finished in 0.90756 seconds
1 examples, 1 failure

Write Dockerfile

Add git installation in Dokcerfile.

RUN apt-get install -y git

Build and run container again with above command.

Run test (Green)

This time test must be pass.

$ rspec
.

Finished in 0.90842 seconds
1 examples, 0 failures

Conclusion

It is easy. We can test package installation by Dockerfile. With serversepc and Docker API, we can almost test
Dockerfile we create. With serverspec, we can confirm more complex server state. For more details, please see official document.

1 Response
Add your response

Thanks got this working great. Did you ever find an elegant way to switch your SSH port for each spec.rb file. I am looking for a way to pass in the ssh port for a container into the spec helper.

over 1 year ago ·