Answers: <p>I'm not going to answer why you can't ssh to your container. There might be a dozen reasons which are impossible to guess with as little information provided in your question. Moreover, installing ssh inside a container is usually not a good idea anyway.</p>
  <p>In fact, your assumption is wrong:</p>
  <blockquote>
  <p>For Ansible to work, it needs to be able to ssh into the host</p>
  </blockquote>
  <p>Actually, for Ansible &quot;to work&quot; i.e. to be able to control targets from a controller, you need a way to connect to the target. And even if ssh is the most common, it's not the only one. There's actually a <a href="https://docs.ansible.com/ansible/latest/collections/community/docker/docker_connection.html" rel="nofollow noreferrer">specific connection plugin</a> to connect to docker containers. The only real prerequisite is to have python inside the target.</p>
  <p>There's also a <a href="https://docs.ansible.com/ansible/latest/collections/community/docker/docker_containers_inventory.html" rel="nofollow noreferrer">dynamic inventory plugin</a> that will collect all hosts running on a specific docker daemon.</p>
  <p>If you really want to create a lab running entirely inside docker and with Ansible running in one of the containers, this is what I suggest as a basic scaffold. You can adapt to your exact needs</p>
  <p>Project structure:</p>
  <pre class="lang-none prettyprint-override"><code>$ tree lab
  lab
  ├── ansible-lab
  │   ├── dummy_playbook.yml
  │   └── inventories
  │       └── default
  │           └── hosts_docker.yml
  ├── compose.yml
  └── images
      ├── controller
      │   └── Dockerfile
      └── target
          └── Dockerfile
  
  6 directories, 5 files
  </code></pre>
  <p>I used the same base image as in your example. Here is <code>images/controller/Dockerfile</code> for the Ansible controller (side note: please refrain from installing Ansible through your package manager and use pip which is now the only officially supported method)</p>
  <pre><code>FROM rockylinux:8.8
  
  WORKDIR /ansible-lab
  
  RUN \
    dnf update -y &amp;&amp; \
    dnf install -y dnf-plugins-core &amp;&amp; \
    dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo &amp;&amp; \
    dnf install -y python3.8 docker-ce-cli bash-completion &amp;&amp; \
    python3 -m pip install --upgrade pip &amp;&amp; \
    # Note: the docker python lib is required for docker connection and inventory plugins
    pip install ansible docker
  </code></pre>
  <p>This is the <code>images/target/Dockerfile</code> for the target host(s) we will manage</p>
  <pre><code>FROM rockylinux:8.8
  RUN \
    dnf update -y &amp;&amp; \
    dnf install -y python3.8
  </code></pre>
  <p>The <code>compose.yml</code> file puts everything together:</p>
  <pre class="lang-yaml prettyprint-override"><code>---
  services:
    controller:
      image: rocky_ansible_controller:local
      build: images/controller
      container_name: lab-controller
      command: tail -f /dev/null
      volumes:
        # Access our ansible project which can be edited from the host if needed
        - ./ansible-lab:/ansible-lab
        # We mount the host docker socket so we can access docker containers
        # running there from the container with the docker cli
        - /var/run/docker.sock:/var/run/docker.sock
  
    host:
      image: rocky_ansible_target:local
      build: images/target
      command: tail -f /dev/null
  </code></pre>
  <p>Let's build and start our project with a single target host for now:</p>
  <pre><code>$ cd lab
  $ docker compose build
  [... lots of build output cut out ...]
  
  $ docker compose up -d
  [+] Running 3/3
   ✔ Network lab_default       Created    0.0s 
   ✔ Container lab-host-1      Started    1.0s 
   ✔ Container lab-controller  Started    1.1s 
  </code></pre>
  <p>Now here is our basic inventory <code>ansible-lab/inventories/default/hosts_docker.yml</code> using the docker-container inventory plugin (see link above- important: it must end with '_docker.yml' as explained in the documentation)</p>
  <p><em>Note that the <code>lab-</code> prefix for containers is taken from the directory name holding the compose project. If your directory has an other name than <code>lab</code>, you'll have to adapt below or to <a href="https://docs.docker.com/engine/reference/commandline/compose/#use--p-to-specify-a-project-name" rel="nofollow noreferrer">set the project name yourself</a>.</em></p>
  <pre class="lang-yaml prettyprint-override"><code>---
  plugin: community.docker.docker_containers
  docker_host: unix://var/run/docker.sock
  connection_type: docker-cli
  compose:
    # All host will be accessed through docker
    ansible_connection: docker
    # Don't use platform python but the one specifically installed
    ansible_python_interpreter: &quot;'/usr/bin/python3'&quot;
  groups:
    # This creates a lab_hosts group for all hostnames starting with 'lab-host-'
    lab_hosts: inventory_hostname is match('^lab-host-.*$')
  </code></pre>
  <p>And here is the basic <code>ansible-lab/dummy-playbook.yml</code> which will simply install a new package on the hosts:</p>
  <pre class="lang-yaml prettyprint-override"><code>---
  - name: Dummy playbook for lab
    hosts: lab_hosts
  
    tasks:
      - name: Install a package on host
        ansible.builtin.dnf:
          name: bind-utils
          state: present
  </code></pre>
  <p>We can run this playbook using the inventory from the controller (note that the ansible files are mounted directly inside the container working directory, see the compose file)</p>
  <pre class="lang-bash prettyprint-override"><code>$ docker compose exec controller ansible-playbook -i inventories/default dummy_playbook.yml
  
  PLAY [Dummy playbook for lab] ********************************************************************************************************************************************************************************************************
  
  TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************
  ok: [lab-host-1]
  
  TASK [Install a package on host] *****************************************************************************************************************************************************************************************************
  changed: [lab-host-1]
  
  PLAY RECAP ***************************************************************************************************************************************************************************************************************************
  lab-host-1                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  </code></pre>
  <p>Let's start some more target just to show it's working as intended and scales</p>
  <pre class="lang-bash prettyprint-override"><code>docker compose up -d --scale host=3
  [+] Running 4/4
   ✔ Container lab-host-1      Running    0.0s 
   ✔ Container lab-host-3      Started    0.5s 
   ✔ Container lab-host-2      Started    0.6s 
   ✔ Container lab-controller  Running    0.0s 
  
  $ docker compose exec controller ansible-playbook -i inventories/default dummy_playbook.yml
  
  PLAY [Dummy playbook for lab] ********************************************************************************************************************************************************************************************************
  
  TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************
  ok: [lab-host-3]
  ok: [lab-host-2]
  ok: [lab-host-1]
  
  TASK [Install a package on host] *****************************************************************************************************************************************************************************************************
  ok: [lab-host-1]
  changed: [lab-host-2]
  changed: [lab-host-3]
  
  PLAY RECAP ***************************************************************************************************************************************************************************************************************************
  lab-host-1                 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
  lab-host-2                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
  lab-host-3                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  </code></pre>
  <p>Of course you'll want to do many more things with those containers. But at any time you can simply restart from scratch. Just shut down everything and start over:</p>
  <pre class="lang-bash prettyprint-override"><code>$ docker compose down 
  [+] Running 5/5
   ✔ Container lab-host-1      Removed    10.6s 
   ✔ Container lab-host-2      Removed    10.5s 
   ✔ Container lab-host-3      Removed    10.4s 
   ✔ Container lab-controller  Removed    10.5s 
   ✔ Network lab_default       Removed    0.5s 
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2023-10-22T16:53:52.537Z
Answers: 2023-10-22T17:23:06.063Z
Answers: 2023-10-22T17:23:06.063Z
Answers: Zeitounator
Body: <p>I'm trying to setup a mini ansible lab with docker containers. I have 1 Rockylinux based container as the ansible controller, and then (for right now) 1 Rockylinux based container as the host.</p>
  <p>For ansible to work, it needs to be able to ssh into the host. I've installed opensh and configured for root login and I'm still getting connection refused whenever I try.</p>
  <p>Any config that I'm missing?</p>
  <p>my Dockerfiles are pretty basic. Here is the file for the ansible server:</p>
  <pre><code>FROM rockylinux:8.8
  RUN dnf update -y &amp;&amp; \
  dnf install python38 -y &amp;&amp; \ 
  dnf install ansible-core -y &amp;&amp;\
  dnf install openssh -y &amp;&amp; \
  dnf install openssh-server -y &amp;&amp; \
  dnf install vim -y &amp;&amp; \
  dnf install net-tools -y 
  EXPOSE 22
  </code></pre>
  <p>the &quot;host&quot; server is the same except there isn't ansible-core installed</p>
  <p>any reason why I can't ssh from one container to the other?</p>
  
Comments: CC BY-SA 4.0
Comments: 2023-10-22T14:59:55.743Z
Comments: I don't see any entrypoint nor command launching the ssh daemon in your example hence how do you start it and make sure it is running prior to attempting to connect?
Comments: Zeitounator
Tags: <docker><ansible>
Title: Trying to Create a Docker Ansible lab and Cant SSH
UserDisplayName: egkennedy93
ThreadText: # Trying to Create a Docker Ansible lab and Cant SSH
  
  (Asked by: username_0 on 2023-10-20)
  
  I'm trying to setup a mini ansible lab with docker containers. I have 1 Rockylinux based container as the ansible controller, and then (for right now) 1 Rockylinux based container as the host.
  
  For ansible to work, it needs to be able to ssh into the host. I've installed opensh and configured for root login and I'm still getting connection refused whenever I try.
  
  Any config that I'm missing?
  
  my Dockerfiles are pretty basic. Here is the file for the ansible server:
  
  ```
  FROM rockylinux:8.8
  RUN dnf update -y && \
  dnf install python38 -y && \ 
  dnf install ansible-core -y &&\
  dnf install openssh -y && \
  dnf install openssh-server -y && \
  dnf install vim -y && \
  dnf install net-tools -y 
  EXPOSE 22
  
  ```
  
  the "host" server is the same except there isn't ansible-core installed
  
  any reason why I can't ssh from one container to the other?
  
  **Tags:** docker, ansible
  
  > **Comments:**
  > **username_1**: I don't see any entrypoint nor command launching the ssh daemon in your example hence how do you start it and make sure it is running prior to attempting to connect?  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2023-10-22. Score: 1
  
  I'm not going to answer why you can't ssh to your container. There might be a dozen reasons which are impossible to guess with as little information provided in your question. Moreover, installing ssh inside a container is usually not a good idea anyway.
  
  In fact, your assumption is wrong:
  
  > For Ansible to work, it needs to be able to ssh into the host
  
  Actually, for Ansible "to work" i.e. to be able to control targets from a controller, you need a way to connect to the target. And even if ssh is the most common, it's not the only one. There's actually a [specific connection plugin](https://docs.ansible.com/ansible/latest/collections/community/docker/docker_connection.html) to connect to docker containers. The only real prerequisite is to have python inside the target.
  
  There's also a [dynamic inventory plugin](https://docs.ansible.com/ansible/latest/collections/community/docker/docker_containers_inventory.html) that will collect all hosts running on a specific docker daemon.
  
  If you really want to create a lab running entirely inside docker and with Ansible running in one of the containers, this is what I suggest as a basic scaffold. You can adapt to your exact needs
  
  Project structure:
  
  ```none
  $ tree lab
  lab
  ├── ansible-lab
  │   ├── dummy_playbook.yml
  │   └── inventories
  │       └── default
  │           └── hosts_docker.yml
  ├── compose.yml
  └── images
      ├── controller
      │   └── Dockerfile
      └── target
          └── Dockerfile
  
  6 directories, 5 files
  
  ```
  
  I used the same base image as in your example. Here is `images/controller/Dockerfile` for the Ansible controller (side note: please refrain from installing Ansible through your package manager and use pip which is now the only officially supported method)
  
  ```
  FROM rockylinux:8.8
  
  WORKDIR /ansible-lab
  
  RUN \
    dnf update -y && \
    dnf install -y dnf-plugins-core && \
    dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \
    dnf install -y python3.8 docker-ce-cli bash-completion && \
    python3 -m pip install --upgrade pip && \
    # Note: the docker python lib is required for docker connection and inventory plugins
    pip install ansible docker
  
  ```
  
  This is the `images/target/Dockerfile` for the target host(s) we will manage
  
  ```
  FROM rockylinux:8.8
  RUN \
    dnf update -y && \
    dnf install -y python3.8
  
  ```
  
  The `compose.yml` file puts everything together:
  
  ```yaml
  ---
  services:
    controller:
      image: rocky_ansible_controller:local
      build: images/controller
      container_name: lab-controller
      command: tail -f /dev/null
      volumes:
        # Access our ansible project which can be edited from the host if needed
        - ./ansible-lab:/ansible-lab
        # We mount the host docker socket so we can access docker containers
        # running there from the container with the docker cli
        - /var/run/docker.sock:/var/run/docker.sock
  
    host:
      image: rocky_ansible_target:local
      build: images/target
      command: tail -f /dev/null
  
  ```
  
  Let's build and start our project with a single target host for now:
  
  ```
  $ cd lab
  $ docker compose build
  [... lots of build output cut out ...]
  
  $ docker compose up -d
  [+] Running 3/3
   ✔ Network lab_default       Created    0.0s 
   ✔ Container lab-host-1      Started    1.0s 
   ✔ Container lab-controller  Started    1.1s 
  
  ```
  
  Now here is our basic inventory `ansible-lab/inventories/default/hosts_docker.yml` using the docker-container inventory plugin (see link above- important: it must end with '\_docker.yml' as explained in the documentation)
  
  *Note that the `lab-` prefix for containers is taken from the directory name holding the compose project. If your directory has an other name than `lab`, you'll have to adapt below or to [set the project name yourself](https://docs.docker.com/engine/reference/commandline/compose/#use--p-to-specify-a-project-name).*
  
  ```yaml
  ---
  plugin: community.docker.docker_containers
  docker_host: unix://var/run/docker.sock
  connection_type: docker-cli
  compose:
    # All host will be accessed through docker
    ansible_connection: docker
    # Don't use platform python but the one specifically installed
    ansible_python_interpreter: "'/usr/bin/python3'"
  groups:
    # This creates a lab_hosts group for all hostnames starting with 'lab-host-'
    lab_hosts: inventory_hostname is match('^lab-host-.*$')
  
  ```
  
  And here is the basic `ansible-lab/dummy-playbook.yml` which will simply install a new package on the hosts:
  
  ```yaml
  ---
  - name: Dummy playbook for lab
    hosts: lab_hosts
  
    tasks:
      - name: Install a package on host
        ansible.builtin.dnf:
          name: bind-utils
          state: present
  
  ```
  
  We can run this playbook using the inventory from the controller (note that the ansible files are mounted directly inside the container working directory, see the compose file)
  
  ```bash
  $ docker compose exec controller ansible-playbook -i inventories/default dummy_playbook.yml
  
  PLAY [Dummy playbook for lab] ********************************************************************************************************************************************************************************************************
  
  TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************
  ok: [lab-host-1]
  
  TASK [Install a package on host] *****************************************************************************************************************************************************************************************************
  changed: [lab-host-1]
  
  PLAY RECAP ***************************************************************************************************************************************************************************************************************************
  lab-host-1                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  
  ```
  
  Let's start some more target just to show it's working as intended and scales
  
  ```bash
  docker compose up -d --scale host=3
  [+] Running 4/4
   ✔ Container lab-host-1      Running    0.0s 
   ✔ Container lab-host-3      Started    0.5s 
   ✔ Container lab-host-2      Started    0.6s 
   ✔ Container lab-controller  Running    0.0s 
  
  $ docker compose exec controller ansible-playbook -i inventories/default dummy_playbook.yml
  
  PLAY [Dummy playbook for lab] ********************************************************************************************************************************************************************************************************
  
  TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************
  ok: [lab-host-3]
  ok: [lab-host-2]
  ok: [lab-host-1]
  
  TASK [Install a package on host] *****************************************************************************************************************************************************************************************************
  ok: [lab-host-1]
  changed: [lab-host-2]
  changed: [lab-host-3]
  
  PLAY RECAP ***************************************************************************************************************************************************************************************************************************
  lab-host-1                 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
  lab-host-2                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
  lab-host-3                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  
  ```
  
  Of course you'll want to do many more things with those containers. But at any time you can simply restart from scratch. Just shut down everything and start over:
  
  ```bash
  $ docker compose down 
  [+] Running 5/5
   ✔ Container lab-host-1      Removed    10.6s 
   ✔ Container lab-host-2      Removed    10.5s 
   ✔ Container lab-host-3      Removed    10.4s 
   ✔ Container lab-controller  Removed    10.5s 
   ✔ Network lab_default       Removed    0.5s 
  
  ```
  
  
  ---
  
  