Ansible's docker module volumes option is a mystery (to me)

4,031 views
Skip to first unread message

Steven Truong

unread,
Aug 26, 2014, 3:05:49 PM8/26/14
to ansible...@googlegroups.com
Hi all,

I tried to use the volumes option and nothing seems to work for me.
  
I want to mount 2 directories ~/dockerstorage/model and ~/repo/ops/ansible to the container and I used either of these commands and nothing worked.

 docker: image=registry.my.com:5000/steven/centos65_prod_ready:v1 docker_url=tcp://{{ ansible_default_ipv4.address }}:7777 publish_all_ports=True state=running volumes=/home/kafka/models:{{ myhome.stdout }}/dockerstorage/models:rw,/usr/local/src/ansible:{{ myhome.stdout }}/repo/ops/ansible:ro   

 docker: image=registry.my.com:5000/steven/centos65_prod_ready:v1 docker_url=tcp://{{ ansible_default_ipv4.address }}:7777 publish_all_ports=True state=running volumes={{ myhome.stdout }}/dockerstorage/models:/home/kafka/models:rw,{{ myhome.stdout }}/repo/ops/ansible:/usr/local/src/ansible:ro

I sshed into the containers and the mounted points in either case were all empty.

I ran using docker directly and it worked for me:


docker run -d -P  -v /home/steven/dockerstorage/models:/home/kafka/models:rw -v /home/steven/repo/ops/ansible:/usr/local/src/ansible:ro registry.my.com:5000/steven/centos65_prod_ready:v1



Please let me know what is the right ways to use "volumes" for docker.  From the comments in the docker module, it appears to me that the /mnt:/tmp is in reversed orders from those of the docker command line because of the case when we just want to create a volume such as /mnt and there is no equivalent mounted point from the host.  I think that this is confusing and users have to read the codes to find out.

Thanks,
Steven.

[root@sc2-dock1 cloud]# pwd
/usr/local/ansible/library/cloud


class DockerManager:

    counters = {'created':0, 'started':0, 'stopped':0, 'killed':0, 'removed':0, 'restarted':0, 'pull':0}

    def __init__(self, module):
        self.module = module  

        self.binds = None
        self.volumes = None
        if self.module.params.get('volumes'):
            self.binds = {}
            self.volumes = {}
            vols = self.module.params.get('volumes')
            for vol in vols:
                parts = vol.split(":")
                # host mount (e.g. /mnt:/tmp, bind mounts host's /tmp to /mnt in the container)
                if len(parts) == 2:
                    self.volumes[parts[1]] = {}
                    self.binds[parts[0]] = parts[1]
                # docker mount (e.g. /www, mounts a docker volume /www on the container at the same location)
                else:
                    self.volumes[parts[0]] = {}



James Cammarata

unread,
Aug 26, 2014, 3:16:30 PM8/26/14
to ansible...@googlegroups.com
If you remove the variables and hard-code the paths, does it work for you then? I'm curious if things like spaces/newlines in the stdout variables you're using are causing the problem.

You might want to put in a "- debug: var=myhome" before the docker task to view the value of stdout there.


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/40310529-7426-4321-b9a6-20a9f73d9005%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Steven Truong

unread,
Aug 26, 2014, 3:26:57 PM8/26/14
to ansible...@googlegroups.com
TASK: [echo $myhome] ********************************************************** 
ok: [localhost] => {
    "myhome": {
        "changed": true, 
        "cmd": "echo $HOME", 
        "delta": "0:00:00.165168", 
        "end": "2014-08-26 19:22:36.055947", 
        "invocation": {
            "module_args": "echo $HOME", 
            "module_name": "shell"
        }, 
        "rc": 0, 
        "start": "2014-08-26 19:22:35.890779", 
        "stderr": "", 
        "stdout": "/root", 
        "stdout_lines": [
            "/root"
        ]
    }
}


I removed :rw and :ro and it still did not work. I think that Ansible does not support these third fields yet.

Steven.

James Cammarata

unread,
Aug 26, 2014, 8:27:59 PM8/26/14
to ansible...@googlegroups.com
I merged in support for specifying :ro/:rw a few weeks ago, and it was included in the 1.7.1 release.


Matt Hughes

unread,
Sep 8, 2014, 12:09:03 PM9/8/14
to ansible...@googlegroups.com
Volumes also don't appear to be working for me either.  I can start the container, but the mounted volume is always empty inside the container, despite the host having two volumes.  As the original poster says, if I just use the docker command directly, the volume mount works as expected.

- name: Start Registry
  docker: image={{docker_image}} state=running volumes="/etc/docker-registry/keys:/etc/docker-registry/keys" name=registry

See anything wrong?

Michael DeHaan

unread,
Sep 8, 2014, 5:41:18 PM9/8/14
to ansible...@googlegroups.com
Can you share the version of Ansible, docker-py, and Docker being used in this case?

Thanks!



Matt Hughes

unread,
Sep 8, 2014, 5:44:55 PM9/8/14
to ansible...@googlegroups.com
[clduser@docker-registry ~]$ sudo docker -v
Docker version 1.1.2, build d84a070/1.1.2

[clduser@docker-registry ~]$ pip list | grep docker
docker-py (0.4.0)

Using the latest ‘devel’ branch of Ansible.  Just repulled now and still experiencing this as of commit c610783f900586b170a6dfa3a02696f568a11728.
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/tjBFAN1Qc7w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.

To post to this group, send email to ansible...@googlegroups.com.

Michael DeHaan

unread,
Sep 9, 2014, 12:43:38 PM9/9/14
to ansible...@googlegroups.com
Ok can you please file a ticket on this one so we can investigate?

Thanks!

Matt Hughes

unread,
Sep 12, 2014, 9:08:08 AM9/12/14
to ansible...@googlegroups.com
So I actually got this working.  It think some of my confusion comes from how to specify 'list' variables.  The docker module, says the 'volumes' parameter was a 'list'.  Being new to Ansible and with no volumes example, I dug around a bit.  EC2 module has a 'list' var of instance-ids and this example:

vars:
    instance_ids
:
     
- 'i-xxxxxx'
     
- 'i-xxxxxx'
     
- 'i-xxxxxx'
    region
: us-east-1
  tasks
:
   
- name: Start the sandbox instances
      local_action
:
       
module: ec2
        instance_ids
: '{{ instance_ids }}'

So I tried to copy that with docker:

  vars:
    theVolumes
:
     
- '/etc/foo:/foo'
     
- '/etc/bar:/bar'
  tasks
:
   
- name: run bash
      docker
:
        image
=centos
        volumes
='{{ theVolumes }}'
        state
=running
        stdin_open
=yes tty=yes
        command
=/bin/bash

But docker client does not like that.

<96.119.0.167> REMOTE_MODULE docker image=centos volumes='['/etc/foo:/foo', '/etc/bar:/boo']' state=running stdin_open=yes tty=yes command=/bin/bash
msg: Docker API error: Cannot start container 35fb847fdc84ff5bcbdce19b9a443a4eb86de5018d96fd620ca22dcb7dc4f3b0:  /etc/bar must be an absolute path

Despite the fact that it appears to have parse the volumes correctly, I get the absolute path error seen above.  If I change the command to:

  tasks:
   
- name: run bash
      docker
:
        image
=centos
        volumes
='/etc/foo:foo,/etc/bar:bar'
        state
=running
        stdin_open
=yes tty=yes
        command
=/bin/bash



My guess is that this works with ec2 because that's running locally, but docker has to serialize the list to the server?  I think my other issues were red-herrings and I was getting confused reading the code.  How does the docker module know that a string with commas in it is a list?


        if self.module.params.get('volumes'):
           
self.binds = {}
           
self.volumes = {}
            vols
= self.module.params.get('volumes')
           
for vol in vols:


Is the fact that it is annotated a 'list' in the module spec (volumes= dict(default=None, type='list')) make Ansible 'pre-parse' that String into a List?  Should the user really have to change how they specify a list based on whether it is executed locally or remotely?  I am able to use var if I do this:

  vars:
    theVolumes
:
     
- '/etc/foo:/foo'
     
- '/etc/bar:/bar'
  tasks
:
   
- name: run bash
      docker
:
        image
=centos
        volumes
={{ theVolumes | join(',') }}
        state
=running
        stdin_open
=yes tty=yes
        command
=/bin/bash



But IMO if their is Ansible magic with lists going on, it should do that already.

Bk Lau

unread,
Sep 26, 2014, 2:56:53 PM9/26/14
to ansible...@googlegroups.com
Any final  prognosis on this issue? Specfically, how should the volumes be specified. An example would be nice!
I'm urgently waiting to use this feature.
--BK

James Cammarata

unread,
Sep 26, 2014, 3:41:36 PM9/26/14
to ansible...@googlegroups.com
@Matt - the issue you're seeing is due to the fact that your missing YAML lists with the k=v syntax for modules. If you used the "complex arguments" syntax for the module, you wouldn't have to do the join. For example:

  vars: 
    theVolumes:
      - '/etc/foo:/foo'
      - '/etc/bar:/bar'
  tasks:
    - name: run bash
      docker: 
        image: centos
        volumes: "{{ theVolumes }}"
        state: running
        stdin_open: yes
        tty: yes
        command: /bin/bash

should work without any issues.

Michael DeHaan

unread,
Sep 27, 2014, 9:39:24 AM9/27/14
to ansible...@googlegroups.com
The user does not have to change how they specify a list based on it being local or remote - that is not a thing in Ansible.

You do need to use the ":" form in the arguments though, any time you want to pass structured data to a module.



Matt Hughes

unread,
Sep 29, 2014, 9:25:09 AM9/29/14
to ansible...@googlegroups.com
Ah, so = does an implicit 'toString' on the variable I presume?

Michael DeHaan

unread,
Sep 29, 2014, 9:42:39 AM9/29/14
to ansible...@googlegroups.com
Yeah basically - it's Jinja2 templated down to a string, losing any type info.




Lokesh Dokara

unread,
Dec 22, 2014, 11:03:56 AM12/22/14
to ansible...@googlegroups.com
Hi all,

Docker volumes worked fine for me as long as I use ansible to run docker on local system, but not working fine when I try to use ansible to run docker on a remote node. My question is whether docker expects the host directory in volumes option to be on system running ansible or the remote node. I've got no results when I had host directory in remote node. 

Matt Hughes

unread,
Dec 23, 2014, 2:04:08 PM12/23/14
to ansible...@googlegroups.com
The volumes need to be where docker is running.   So yes, host directory should be on the remote node running docker.

Lokesh Dokara

unread,
Dec 26, 2014, 6:13:32 AM12/26/14
to ansible...@googlegroups.com
But ansible module is not working properly on remote nodes

Matt Hughes

unread,
Dec 26, 2014, 12:34:56 PM12/26/14
to ansible...@googlegroups.com
Do you have the required Python module installed on the remote node?  I believe it is docker-py but check the docket module to be sure.


--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/tjBFAN1Qc7w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Lokesh Dokara

unread,
Dec 26, 2014, 1:03:42 PM12/26/14
to ansible...@googlegroups.com
Yeah latest version (0.7.0) of docker-py is installed. Except volumes option all other docker options are working fine. 


For more options, visit https://groups.google.com/d/optout.



--
Lokesh Dokara,
Department of Computer Science and Engineering,
I.I.T. Kharagpur
Reply all
Reply to author
Forward
0 new messages