Running service
resources in Kitchen-Docker
When writing cookbooks, you need to actually test that they work. This is often done using Test Kitchen, a tool that allows you to converge your cookbooks on a real machine. There are a number of drivers that can be used, such as kitchen-vagrant and kitchen-docker.
For instance, I run against Docker due to its incredible speed compared to running on a virtual machine, and also due to the fact that this means I can use Docker with GitLab CI.
Getting kitchen-docker set up
For instance, let's assume we have a .kitchen.yml
configured to use Vagrant as a driver:
driver:
name: docker
provisioner:
name: chef_zero
# You may wish to disable always updating cookbooks in CI or other testing environments.
# For example:
# always_update_cookbooks: <%= !ENV['CI'] %>
always_update_cookbooks: true
verifier:
name: inspec
platforms:
- name: debian
driver_config:
image: debian:jessie
suites:
- name: default
run_list:
- recipe[cookbook::default]
verifier:
inspec_tests:
- test/smoke/default
attributes:
However, when running any of the kitchen commands, you may encounter the following error:
$ kitchen list
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::UserError
>>>>>> Message: You must first install the Docker CLI tool http://www.docker.io/gettingstarted/
>>>>>> ----------------------
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose --all` for configuration
This is due to the Docker driver not being able to correctly find the CLI tool. An easy fix is to add the following to our driver
section in the .kitchen.yml
:
driver:
name: docker
+ # make kitchen detect the Docker CLI tool correctly, via
+ # https://github.com/test-kitchen/kitchen-docker/issues/54#issuecomment-203248997
+ use_sudo: false
Running service commands
Next, we want to be able to interact with services via Chef's service
resources. Trying to interface with a service in a Docker container results in the following error:
$ sudo systemctl restart mysql
Failed to get D-Bus connection: Operation not permitted
This is due to the whole point of docker containers running a single application. When trying to interface with a service
, this requires a full init system, with multiple processes running on top of it. This means that you're using Docker for something it's not built for (out of the box).
Therefore, you need to extend the Docker container to have its own init system, as well as giving it root access across the host system: that is, this new container that is meant to be separate, and have its own nicely sandboxed resources will have root access to your machine. Be aware of the security risks this can cause on your machine - I have no responsibility for issues caused.
Following the advice in Stack Overflow: Kitchen-Docker and Systemd:
driver:
name: docker
# make kitchen detect the Docker CLI tool correctly, via
# https://github.com/test-kitchen/kitchen-docker/issues/54#issuecomment-203248997
use_sudo: false
+ run_command: /bin/systemd
+ cap_add:
+ - SYS_ADMIN
+ volume:
+ - /sys/fs/cgroup
run_command
defines what command should be run by the container, which in this case would be systemd, the init system used by Debian Jessie.
As mentioned, we also need to give it the SYS_ADMIN
capability, which gives it root access across the machine.
Finally, we also need to give it access to the cgroups config, which is an expectation of systemd.