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.
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.
Written by tcnksm
Related protips
1 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.