<p>I have achieved the same goal but a bit more securely, by forwarding the unix socket (but not a tcp socket). However it is a bit convoluted. The following example contains everything from starting an example container, forwarding the socket and tearing down everything afterwards.</p>
<p>In this scenario I have 3 &quot;hosts&quot; (in the sense of ansible hosts), localhost, the server and the container.
Docker-cli must be present on localhost.</p>
<p>My inventory looks like this, I've explicitly specified the forwarded docker socket for the connection to the container:</p>
<pre><code>---
all:
  hosts:
    server:
    container:
      ansible_connection: docker
      ansible_docker_extra_args: &quot;-H unix:///tmp/remote_docker.sock&quot;
  vars:
    docker_sock_path: &quot;/tmp/remote_docker.sock&quot;
</code></pre>
<p>The playbook consists of multiple plays, as it needs to apply to different hosts.</p>
<ol>
<li>At first an <a href="https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160" rel="nofollow noreferrer">ssh-forwarding of the unix-socket</a> is setup. This is done on localhost (however it's not a separate play, just delegated</li>
<li>The docker container is started (this is done on the server).
The container is started with <code>interactive: true</code> so it stays alive without anything to do.</li>
<li>Tasks are run in the Container</li>
<li>The SSH Process is killed and the socket file is deleted (this is done on localhost)</li>
</ol>
<pre><code>---
- name: &quot;Preparing SSH, starting the container&quot;
  hosts: server
  tasks:
  - name: Create SSH tunnel for the unix docker socket
    command: 
      cmd: &quot;ssh -fnNT -L {{ docker_sock_path }}:/var/run/docker.sock {{ ansible_user }}@{{ ansible_host }}&quot;
    delegate_to: localhost
  - name: create connection container
    community.docker.docker_container:
      name: container
      image: python:3.12-slim-bookworm
      state: started
      interactive: true
      entrypoint: &quot;/bin/sh&quot;

- name: &quot;Executing steps in docker container&quot;
  hosts: container
  tasks:
    [...]
- name: &quot;Shutting down proxy container&quot;
  hosts: server
  tasks:
  - name: stop connection container
    community.docker.docker_container:
      name: server
      state: stopped
- name: &quot;Shutting down socket forwarding&quot;
  hosts: localhost
  connection: local
  tasks:
  - name: get process ids
    shell: ps xf
    register: all_pid
  - name: extract pid of our ssh process
    ansible.builtin.set_fact:
     ssh_pid: &quot;{{ item | trim | split | first }}&quot;
    loop: &quot;{{ all_pid.stdout_lines }}&quot;
    when: item is match(&quot;^.*{{docker_sock_path }}:/var/run/docker.sock.*$&quot;)
  - name: kill ssh process
    ansible.builtin.command:
      cmd: &quot;kill {{ ssh_pid }}&quot;
  - name: Remove socket file
    ansible.builtin.file:
      path: &quot;{{ docker_sock_path }}&quot;
      state: absent
</code></pre>

CC BY-SA 4.0
2023-11-13T16:01:52.110Z
2023-11-13T16:01:52.110Z
BenjaminH
<p>With the help of <a href="https://devops.stackexchange.com/users/4427/levi">@Levi</a> (refered to <a href="https://stackoverflow.com/questions/32878795/run-command-inside-of-docker-container-using-ansible/41626257#41626257">Stackoverflow</a>) I managed to find a way to connect straigt into the docker containers using ansibles docker connection driver and the remote API capability of Docker. </p>

<p>First of all you have to expose the API which is by default not the case. Simply add <code>-H tcp://0.0.0.0:1337</code> to the <code>ExecStart</code> constant of the systemd script. Then reload the start script and restart the docker service. (From <a href="https://www.ivankrizsan.se/2016/05/18/enabling-docker-remote-api-on-ubuntu-16-04/" rel="noreferrer">this</a> blogpost) </p>

<p>Then you can list the containers in the inventory file like this:</p>

<pre><code>[containers]
container-name ansible_connection=docker ansible_docker_extra_args="-H tcp://1.2.3.4:1337"
</code></pre>

<p>And execute any playbook like your used to.</p>

<pre><code>ansible-playbook -i docker_inventory playbooks/my_playbook.yml
</code></pre>

<p>The upside of this way of implementing it this way is that you can mix up "real" hosts/vms that are maintained through SSH and Docker containers. One negative thing I have to mention is that the docker API is much slower than using SSH as a control tunnel.</p>

<p><strong>This setup is of cause horribly insecure and its only purpose is to explain the concept. Before using it in production you should read into the security features and limit access to the daemon as far as possible.</strong></p>

CC BY-SA 4.0
2020-04-04T15:13:03.740Z
As you said insecure for remote, but for local development is a great solution! +1
Matteo Gaggiano
CC BY-SA 4.0
2018-07-04T19:52:51.877Z
2018-07-04T20:03:05.653Z
2018-07-04T20:03:05.653Z
davidb
<p>I have automated the setup of several docker containers with ansible. This works pretty well but there are certain recurring tasks that have to be executed within the docker containers.</p>
<p>It is possible to implement this using the <a href="https://docs.ansible.com/ansible/latest/scenario_guides/guide_docker.html" rel="nofollow noreferrer">docker connection driver</a> for ansible but this only seems to work when ansible is running on the host that is the docker runner. This is not the case and I don't want to run ansible on multiple hosts if possible. Is there a better way to use ansible to execute playbooks within containers?</p>
<p>Notes:</p>
<ul>
<li>I know how I can execute commands in a docker container from the host system but I don't only want to execute commands. I want to be able to use Ansible for docker containers as if they where standalone hosts.</li>
<li>I tried it out of curiosity and it works pretty well using ansible directly on the docker runner,... anyway not my favorite solution.</li>
</ul>

CC BY-SA 4.0
2018-07-04T16:45:39.157Z
How about this https://stackoverflow.com/a/41626257/3888850 ?
Levi
CC BY-SA 4.0
2018-07-04T18:02:02.667Z
Well thank you! Wonder why I didn't find that post on my own,.... o.O That would have some security implications but I could deal with that! Im going to report back on it when I had the opportunity to try it out,...
davidb
CC BY-SA 4.0
2018-07-04T19:54:10.177Z
@Levi: thanks for your help I answered my own post describing it in a more understandable way.
davidb
CC BY-SA 4.0
2018-07-05T05:05:02.417Z
In my opinion docker images should be immutable and stateless.
030
CC BY-SA 4.0
2018-07-05T06:05:40.607Z
@030 Well I think that depends on the application in the container. In my scenario signature updates & actions of the application need to be triggered centrally and I need to validate if the progress of the process in the docker container from the outside to trigger SDN Functionallities
davidb
<docker><ansible>
Applying ansible playbook to a docker container on a remote host
davidb
# Applying ansible playbook to a docker container on a remote host

(Asked by: username_0 on 2018-07-04)

I have automated the setup of several docker containers with ansible. This works pretty well but there are certain recurring tasks that have to be executed within the docker containers.

It is possible to implement this using the [docker connection driver](https://docs.ansible.com/ansible/latest/scenario_guides/guide_docker.html) for ansible but this only seems to work when ansible is running on the host that is the docker runner. This is not the case and I don't want to run ansible on multiple hosts if possible. Is there a better way to use ansible to execute playbooks within containers?

Notes:

* I know how I can execute commands in a docker container from the host system but I don't only want to execute commands. I want to be able to use Ansible for docker containers as if they where standalone hosts.
* I tried it out of curiosity and it works pretty well using ansible directly on the docker runner,... anyway not my favorite solution.

**Tags:** docker, ansible

> **Comments:**
> **username_1**: How about this https://stackoverflow.com/a/41626257/3888850 ?  
> **username_0**: Well thank you! Wonder why I didn't find that post on my own,.... o.O That would have some security implications but I could deal with that! Im going to report back on it when I had the opportunity to try it out,...  
> **username_0**: @username_1: thanks for your help I answered my own post describing it in a more understandable way.  
> **username_2**: In my opinion docker images should be immutable and stateless.  
> **username_0**: @username_2 Well I think that depends on the application in the container. In my scenario signature updates & actions of the application need to be triggered centrally and I need to validate if the progress of the process in the docker container from the outside to trigger SDN Functionallities  

---

## 2 answers

### Answer by username_0 on 2018-07-04. Score: 14 | Accepted answer

With the help of @username_1 (refered to Stackoverflow) I managed to find a way to connect straigt into the docker containers using ansibles docker connection driver and the remote API capability of Docker. 
First of all you have to expose the API which is by default not the case. Simply add -H tcp://0.0.0.0:1337 to the ExecStart constant of the systemd script. Then reload the start script and restart the docker service. (From this blogpost) 
Then you can list the containers in the inventory file like this:
[containers]
container-name ansible_connection=docker ansible_docker_extra_args="-H tcp://1.2.3.4:1337"

And execute any playbook like your used to.
ansible-playbook -i docker_inventory playbooks/my_playbook.yml

The upside of this way of implementing it this way is that you can mix up "real" hosts/vms that are maintained through SSH and Docker containers. One negative thing I have to mention is that the docker API is much slower than using SSH as a control tunnel.
This setup is of cause horribly insecure and its only purpose is to explain the concept. Before using it in production you should read into the security features and limit access to the daemon as far as possible.

> **Comments:**
> **username_4**: As you said insecure for remote, but for local development is a great solution! +1  

---

### Answer by username_3 on 2023-11-13. Score: 0

I have achieved the same goal but a bit more securely, by forwarding the unix socket (but not a tcp socket). However it is a bit convoluted. The following example contains everything from starting an example container, forwarding the socket and tearing down everything afterwards.
In this scenario I have 3 "hosts" (in the sense of ansible hosts), localhost, the server and the container.
Docker-cli must be present on localhost.
My inventory looks like this, I've explicitly specified the forwarded docker socket for the connection to the container:
---
all:
  hosts:
    server:
    container:
      ansible_connection: docker
      ansible_docker_extra_args: "-H unix:///tmp/remote_docker.sock"
  vars:
    docker_sock_path: "/tmp/remote_docker.sock"

The playbook consists of multiple plays, as it needs to apply to different hosts.

At first an ssh-forwarding of the unix-socket is setup. This is done on localhost (however it's not a separate play, just delegated
The docker container is started (this is done on the server).
The container is started with interactive: true so it stays alive without anything to do.
Tasks are run in the Container
The SSH Process is killed and the socket file is deleted (this is done on localhost)

---
- name: "Preparing SSH, starting the container"
  hosts: server
  tasks:
  - name: Create SSH tunnel for the unix docker socket
    command: 
      cmd: "ssh -fnNT -L {{ docker_sock_path }}:/var/run/docker.sock {{ ansible_user }}@{{ ansible_host }}"
    delegate_to: localhost
  - name: create connection container
    community.docker.docker_container:
      name: container
      image: python:3.12-slim-bookworm
      state: started
      interactive: true
      entrypoint: "/bin/sh"

- name: "Executing steps in docker container"
  hosts: container
  tasks:
    [...]
- name: "Shutting down proxy container"
  hosts: server
  tasks:
  - name: stop connection container
    community.docker.docker_container:
      name: server
      state: stopped
- name: "Shutting down socket forwarding"
  hosts: localhost
  connection: local
  tasks:
  - name: get process ids
    shell: ps xf
    register: all_pid
  - name: extract pid of our ssh process
    ansible.builtin.set_fact:
     ssh_pid: "{{ item | trim | split | first }}"
    loop: "{{ all_pid.stdout_lines }}"
    when: item is match("^.*{{docker_sock_path }}:/var/run/docker.sock.*$")
  - name: kill ssh process
    ansible.builtin.command:
      cmd: "kill {{ ssh_pid }}"
  - name: Remove socket file
    ansible.builtin.file:
      path: "{{ docker_sock_path }}"
      state: absent


---

