Test Ansible with Docker container

Ansible 2.0 became, and Docker connection plugin entered by standard. This makes it possible to directly execute Ansible without setting sshd in Docker.

Many people have already been introduced, quite a bit now, but here's how to test Ansible against the Docker container.

Restrictions on Docker

First of all, it's about restrictions on running Ansible against Docker container.

Basically all functions are available. However, there are the following restrictions.

  • / Etc / hosts, /etc/resolv.conf, / etc / hostname can not be rewritten

    These files are bind-mounted by Docker and can be rewritten, but can not be replaced. Since / etc / hostname can not be changed, it can not be changed with the hostname module.

There are at least the following problems depending on the image to be executed. There are many other things. This area is about Docker itself, it is not an issue peculiar to Ansible, so please solve it somehow.

  • Systemd's service can not be started

    Because there is no-Bus D, Failed to connect to bus: No such file or directory is said to be. You can start upstart and rc init. CAP_SYS_ADMIN Capability is necessary

  • There may be no sudo

In addition, if you do a test from a slim image, it will take time for downloading, so if you prepare an image with appropriate settings beforehand, I think that the test time will decrease.

Inventory

Well, it is the main issue. How to use Ansible's docker connection plugin

web ansible_connection=docker ansible_host=<コンテナID>

So on, ansible_connection=docker you can use immediately by simply with. However, you must specify a container ID for ansible_host. The container ID of Docker is really temporary, so I write it here only during debugging.

In order to avoid this docker launched a container using the Module, add_host it is also possible to generate a group, you will need to edit for testing the playbook. Even so it may be okay, but let's use the Docker dynamic inventory.

Docker dynamic inventory

GitHubのansibleのリポジトリ from docker.py to get the leave grant execute permissions. docker.yml It does not matter not.

# docker containerを立ち上げる
$ docker run --name <hostsでの指定対象> ubuntu:16.04 /bin/sleep 3600

# 立ち上げたdocker containerに対してansibleを実行する
$ ansible-playbook -i docker.py something.yml

, We get a container ID from the name of the currently running container and use it. Some of the information that can be obtained with docker.py is shown below. In addition to name, you can see that groups are created with image and container ID. However, this time because the test, because you want to use the same name as a regular group name use.

"web": [
  "web"
],
"image_ubuntu:16.04": [
  "web"
],
"zzzzzd5bed36e033fac72d52ae115a2da12f3e08b995325182398aae2a95a": [
  "web"
],
"zzzzz114d5bed": [
  "web"
],
"running": [
  "web"
],
"docker_hosts": [
  "unix://var/run/docker.sock"
],
"unix://var/run/docker.sock": [
  "web"
],

Inventory Directory

If you use dynamic inventory, you may think that group_vars specified in the inventory file may become unusable.

In that case separate the directory and put docker.py and a static file. As inventory file in advance to do so ディレクトリ If you specify, will take the information from both static files and dynamic inventory. When using only with CI, I think that it becomes easier to handle as an Inventory for CI by separating directories.

CircleCI

Let's try it through CI. I will try CircleCI. Circle.yml is like this.

machine:
  services:
    - docker
  environment:
    DOCKER_API_VERSION: "1.20"

dependencies:
  pre:
    - docker pull ubuntu:16.04
    - sudo pip install ansible ansible-lint docker-py

test:
  override:
    - docker run -d --name web ubuntu:16.04 /bin/sleep 3600
    - ansible-playbook -i inventory_docker web.yml test.yml --syntax-check
    - ansible-lint test.yml
    - ansible-playbook -i inventory_docker web.yml test.yml -l running

--syntax-check and ansible-lint we also incidentally. DOCKER_API_VERSION has set for the old is docker of CircleCI. In addition, in the Run Docker --name web it is. This is because you are running on a web group on a regular playbook and you do not want to change that playbook.

When you push it,

fatal: [web]: FAILED! => {"changed": false, "failed": true, "rc": 1, "stderr": "Error response from daemon: Unsupported: Exec is not supported by the lxc driver\n", "stdout": "", "stdout_lines": []}

I was scolded. That's right. CircleCI are using the lxc driver, Docker connection plugin uses docker exec can not I use.

I gave it up for that.

Other CI service is wercker Toka drone.io have you, but we use the Docker These are the first place in the CI, Docker It became in Docker and it is hard work.

Another solution : to provide its own Docker host

Or, of Circle.Yml environment in DOCKER_HOST By setting, can also be run against Docker host stood outside CircleCI. Although it may be easier than using GitLab, which is explained next, please pay special attention to keeping the security settings firm.

GitLab

GitLab is it's fashion recently. I will also introduce you to use this as CI also recently attached.

I omit installing gitlab and gitlab CI runner itself. There is also a CI Runner that runs in Docker, but then it will be Docker in Docker so do not forget to make it shell runner for this application.

From a conclusion, if it firmly to the setting of the runner, such .gitlab-ci.yml you move in. Almost unchanged from CircleCI, after_script is about containing the deletion of the container by.

before_script:
  - pip install ansible ansible-lint docker-py

stages:
  - build

build_job:
  stage: build
  script:
    - docker run -d --name web ubuntu:16.04 /bin/sleep 3600
    - ansible-playbook -i inventory_docker web.yml test.yml --syntax-check
    - ansible-lint test.yml
    - ansible-playbook -i inventory_docker web.yml test.yml -l running

after_script:
  - docker kill `docker ps -aq`
  - docker rm `docker ps -aq`

as the setting of the Runner sudo gpasswd -a $USER docker I think that it may want to be able to use the docker even without sudo to the.

Postscript : Travis CI

@auchida 's from Travis CI if used, was to ask you that. auchidaさんのリポジトリ the decided to reference.

Point sudo: required seems to be putting.

However, probably something seems to be wrong with virtualenv and system, and the following error occurred when running docker dynamic inventory. I want to fix it soon.

class AnsibleDockerClient(Client):
    NameError: name 'Client' is not defined

Thank you very much.

Summary

In this article, I showed you how to test Ansible using the Docker container.

  • Ansible 2.0 can directly ansible to Docker container
  • Although there are some restrictions, it runs fine even on Docker
  • Since it does not work in CircleCI, it introduces the following three methods
    • Prepare your own Docker host
    • Make GitLab and more
    • Use Travis CI

Bonus : Ansible-Lint rules of

Recently we began to establish ansible-lint rules to unify the way we write Playbook within our company. ansible-lint-rules >` _ it has published at.

Although there is no Long description, it is still in the middle, but thank you very much for using Issue and PR if you use it.