Ansible for Docker Containers | Just YAML Things
Why Even Run Docker Containers with Ansible?
Well, I’m running my stuff in a Swarm. The problem is that Swarm does not (yet) allow you to configure Linux Kernel Capabilities on a container. But you can configure them with
docker run. Lame.
Fortunately, I’m using Ansible to deploy some things on this server, so I have things in place already to use it to run a container.
I’m using Traefik as my Reverse Proxy. Traefik works best for dynamic service discovery through the use of Container Labels , or Service Labels. The distinction is very important, depending upon how you’re scheduling your containers.
What’s weird though, is with the labels shown below for my Ansible play… I would get cryptic errors about type conversion. YAML tries to implicitly detect the type of the value (See Ansible Docs on YAML for more detail).
labels: traefik.port: 9980
Will yield this error:
msg: 'Error creating container: 500 Server Error: Internal Server Error ("json: cannot unmarshal number into Go value of type string")' labels: traefik.enable: true
Will yield this error
msg: 'Error creating container: 500 Server Error: Internal Server Error ("json: cannot unmarshal bool into Go struct field ContainerConfigWrapper.Labels of type string")'
To avoid YAML interpreting the type for the value of a dictionary, enclose the value in quotes:
labels: traefik.enable: "true" traefik.port: "9980"
Ansible Troubleshooting Tip
One pain about Ansible is the inconsistency with configuration files. It’s just all over the place with presenting data structures..
- Ansible’s config file,
ansible.cfg, by default is in an
iniformat. Same for
hosts, except that can be in YAML too.
stdoutfrom Ansible is not composed in a very structured way, by default.
But you can have it output things in a more consistent way (since plays are written in YAML ). Export this environment variable to make verbose output print as YAML :
And here’s example output of an error when using
-vvv flags, but much more readable than default:
The full traceback is: File "/tmp/ansible_xhulz3r_/ansible_module_docker_container.py", line 1966, in container_create new_container = self.client.create_container(image, **create_parameters) File "/usr/lib/python3/dist-packages/docker/api/container.py", line 449, in create_container return self.create_container_from_config(config, name) File "/usr/lib/python3/dist-packages/docker/api/container.py", line 460, in create_container_from_config return self._result(res, True) File "/usr/lib/python3/dist-packages/docker/api/client.py", line 226, in _result self._raise_for_status(response) File "/usr/lib/python3/dist-packages/docker/api/client.py", line 222, in _raise_for_status raise create_api_error_from_http_exception(e) File "/usr/lib/python3/dist-packages/docker/errors.py", line 31, in create_api_error_from_http_exception raise cls(e, response=response, explanation=explanation) fatal: [18.104.22.168]: FAILED! => changed=false invocation: module_args: api_version: null auto_remove: false blkio_weight: null cacert_path: null capabilities: - MKNOD