Hi all!
I found an issue with the docker module that I ended up discussing with Paul Durivage. The essential problem is that there is a list of dictionaries per container that only contains the last running container when using “with_sequence” or “with_items” versus “count”, hence making it impossible to utilize information for the entirety of a running fleet of docker containers outside of a task using the docker module.
An idea to deal with this short-coming would be to have a “docker_facts” module for obtaining information from the fleet of Docker containers.
This issue can be better explained with a little code if my short description doesn’t.
The documentation(http://docs.ansible.com/docker_module.html#options) has several examples on how to use the docker module that I tried out. I wanted to get familiar with the basics of this module. The first thing of course was that I wanted to launch simply 4 instances and return some simple information as to what the IPs were:
- hosts: localhost
vars:
start_containers_count: 4
tasks: - name: run docker containers
docker: image=df02bd73464a name=ssh{{ item }}
with_sequence: count={{ start_containers_count }} - name: print debug
debug: msg=“docker_containers[{{item}}][‘NetworkSettings’][‘IPAddress’]}}”
with_items: docker_containers
with_sequence: count={{ start_containers_count }}
Upon running this, the containers were launched just fine, but the debug didn’t output what I expected it to. For starters, there was only one debug line. Also, it appeared there was only information for the last launched container (172.17.0.5). This made me realize something was up.
TASK: [print debug] ***********************************************************
ESTABLISH CONNECTION FOR USER: patg
ok: [localhost] => (item={u’HostsPath’: u’/var/lib/docker/containers/73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921/hosts’, u’Created’: u’2014-04-18T21:43:08.968061193Z’, u’Image’: u’df02bd73464ae121ac3db7788e042d52805c9283b6174511dbf1a6b821ef20c2’, u’Args’: , u’Driver’: u’aufs’, u’HostConfig’: {u’Binds’: None, u’Dns’: None, u’ContainerIDFile’: u’‘, u’PublishAllPorts’: False, u’Links’: None, u’LxcConf’: None, u’PortBindings’: None, u’DnsSearch’: None, u’Privileged’: False, u’VolumesFrom’: None}, u’Id’: u’73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921’, u’State’: {u’Ghost’: False, u’Pid’: 20113, u’Running’: True, u’FinishedAt’: u’0001-01-01T00:00:00Z’, u’StartedAt’: u’2014-04-18T21:43:08.989599463Z’, u’ExitCode’: 0}, u’ExecDriver’: u’native-0.1’, u’ResolvConfPath’: u’/var/lib/docker/containers/73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921/resolv.conf’, u’Volumes’: {}, u’Path’: u’/usr/local/sbin/sshd.sh’, u’HostnamePath’: u’/var/lib/docker/containers/73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921/hostname’, u’Config’: {u’Env’: [u’HOME=/‘, u’PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin’], u’Hostname’: u’73b860f98c60’, u’Entrypoint’: [u’/usr/local/sbin/sshd.sh’], u’PortSpecs’: None, u’Memory’: 0, u’OnBuild’: None, u’OpenStdin’: False, u’User’: u’‘, u’CpuShares’: 0, u’AttachStdout’: False, u’NetworkDisabled’: False, u’WorkingDir’: u’‘, u’Cmd’: None, u’StdinOnce’: False, u’AttachStdin’: False, u’Volumes’: None, u’MemorySwap’: 0, u’Tty’: False, u’AttachStderr’: False, u’Domainname’: u’‘, u’Image’: u’df02bd73464a’, u’ExposedPorts’: {u’22/tcp’: {}}}, u’VolumesRW’: {}, u’NetworkSettings’: {u’Bridge’: u’docker0’, u’PortMapping’: None, u’Gateway’: u’172.17.42.1’, u’IPPrefixLen’: 16, u’IPAddress’: u’172.17.0.5’, u’Ports’: {u’22/tcp’: None}}, u’Name’: u’/ssh4’}) => {
“item”: {
“Args”: ,
“Config”: {
“AttachStderr”: false,
“AttachStdin”: false,
“AttachStdout”: false,
“Cmd”: null,
“CpuShares”: 0,
“Domainname”: “”,
“Entrypoint”: [
“/usr/local/sbin/sshd.sh”
],
“Env”: [
“HOME=/”,
“PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin”
],
“ExposedPorts”: {
“22/tcp”: {}
},
“Hostname”: “73b860f98c60”,
“Image”: “df02bd73464a”,
“Memory”: 0,
“MemorySwap”: 0,
“NetworkDisabled”: false,
“OnBuild”: null,
“OpenStdin”: false,
“PortSpecs”: null,
“StdinOnce”: false,
“Tty”: false,
“User”: “”,
“Volumes”: null,
“WorkingDir”: “”
},
“Created”: “2014-04-18T21:43:08.968061193Z”,
“Driver”: “aufs”,
“ExecDriver”: “native-0.1”,
“HostConfig”: {
“Binds”: null,
“ContainerIDFile”: “”,
“Dns”: null,
“DnsSearch”: null,
“Links”: null,
“LxcConf”: null,
“PortBindings”: null,
“Privileged”: false,
“PublishAllPorts”: false,
“VolumesFrom”: null
},
“HostnamePath”: “/var/lib/docker/containers/73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921/hostname”,
“HostsPath”: “/var/lib/docker/containers/73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921/hosts”,
“Id”: “73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921”,
“Image”: “df02bd73464ae121ac3db7788e042d52805c9283b6174511dbf1a6b821ef20c2”,
“Name”: “/ssh4”,
“NetworkSettings”: {
“Bridge”: “docker0”,
“Gateway”: “172.17.42.1”,
“IPAddress”: “172.17.0.5”,
“IPPrefixLen”: 16,
“PortMapping”: null,
“Ports”: {
“22/tcp”: null
}
},
“Path”: “/usr/local/sbin/sshd.sh”,
“ResolvConfPath”: “/var/lib/docker/containers/73b860f98c60a9d03d693643895ef2b5aa2dce7a40c2ebf6f4bc3433cd800921/resolv.conf”,
“State”: {
“ExitCode”: 0,
“FinishedAt”: “0001-01-01T00:00:00Z”,
“Ghost”: false,
“Pid”: 20113,
“Running”: true,
“StartedAt”: “2014-04-18T21:43:08.989599463Z”
},
“Volumes”: {},
“VolumesRW”: {}
},
“msg”: “172.17.0.5”
}
I decided to print out the docker_containers list (which each member is a dictionary representing each container in the fleet) and use an explicit loop for all containers and noticed it was the same dictionary every time, containing the last container launched:
- name: print debug
debug: msg=“{{docker_containers}}”
with_sequence: count={{ start_containers_count }}
Produced, 4 times:
ok: [localhost] => (item=4) => {
“item”: “4”,
“msg”: “[{u’HostsPath’: u’/var/lib/docker/containers/6359a341981a818294e5866b3e2a8b51360bfab40e8811ae826c1c3b2eae3e6c/hosts’, u’Created’: u’2014-04-19T12:56:34.173476164Z’, u’Image’: u’df02bd73464ae121ac3db7788e042d52805c9283b6174511dbf1a6b821ef20c2’, u’Args’: , u’Driver’: u’aufs’, u’HostConfig’: {u’PortBindings’: None, u’Links’: None, u’LxcConf’: None, u’ContainerIDFile’: u’‘, u’Binds’: None, u’PublishAllPorts’: False, u’Dns’: None, u’DnsSearch’: None, u’Privileged’: False, u’VolumesFrom’: None}, u’VolumesRW’: {}, u’State’: {u’Ghost’: False, u’Pid’: 25329, u’Running’: True, u’FinishedAt’: u’0001-01-01T00:00:00Z’, u’StartedAt’: u’2014-04-19T12:56:34.198602546Z’, u’ExitCode’: 0}, u’ExecDriver’: u’native-0.1’, u’ResolvConfPath’: u’/var/lib/docker/containers/6359a341981a818294e5866b3e2a8b51360bfab40e8811ae826c1c3b2eae3e6c/resolv.conf’, u’Volumes’: {}, u’Path’: u’/usr/local/sbin/sshd.sh’, u’HostnamePath’: u’/var/lib/docker/containers/6359a341981a818294e5866b3e2a8b51360bfab40e8811ae826c1c3b2eae3e6c/hostname’, u’Config’: {u’Env’: [u’HOME=/‘, u’PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin’], u’Hostname’: u’6359a341981a’, u’Entrypoint’: [u’/usr/local/sbin/sshd.sh’], u’PortSpecs’: None, u’Memory’: 0, u’OnBuild’: None, u’OpenStdin’: False, u’User’: u’‘, u’AttachStderr’: False, u’AttachStdout’: False, u’NetworkDisabled’: False, u’WorkingDir’: u’‘, u’Cmd’: None, u’StdinOnce’: False, u’AttachStdin’: False, u’Volumes’: None, u’MemorySwap’: 0, u’Tty’: False, u’CpuShares’: 0, u’Domainname’: u’‘, u’Image’: u’df02bd73464a’, u’ExposedPorts’: {u’22/tcp’: {}}}, u’Id’: u’6359a341981a818294e5866b3e2a8b51360bfab40e8811ae826c1c3b2eae3e6c’, u’NetworkSettings’: {u’Bridge’: u’docker0’, u’PortMapping’: None, u’Gateway’: u’172.17.42.1’, u’IPPrefixLen’: 16, u’IPAddress’: u’172.17.0.5’, u’Ports’: {u’22/tcp’: None}}, u’Name’: u’/ssh4’}]”
}
Now, if i use “count”, as in the following:
- hosts: localhost
vars:
start_containers_count: 4
tasks: - name: run docker containers
docker: image=df02bd73464a count={{ start_containers_count }} - name: print debug
debug: msg=“{{item[‘NetworkSettings’][‘IPAddress’]}}”
with_items: docker_containers
This worked as I wanted it to in the beginning, except that when using “count”, I cannot name the containers as I did in the above examples because you cannot use “count” and “name” together.
The reason for this is that when “count” is used, _ansible_facts() is only called once and obtains a dictionary with members representing dictionaries for each container, whereas if “with_sequence” is used, _ansible_facts() is called for each iteration of the loop (obvious in retrospect).
What this results in is “docker_container” having the last launched container entry.
Which brings me back to the initial idea from Paul – to have a “docker_facts” module that would make is possible to obtain any information a user needs about the fleet of containers. This would make it possible to loop through all the running containers regardless of whether iterative strategy I want.
Anyhow - that is the idea!
Regards,
Patrick