Ansible II: playbooks, containers and inventory

hmartinezdev profile image Héctor Martínez Originally published at hectormartinez.dev ・4 min read

Syndicated content! Check the original "Ansible II: playbooks, containers and inventory" @ hectormartinez.dev

Welcome to the Ansible series! This is the second article in which we will start by creating our first SSH Docker container to simulate one remote machine, write an inventory and build a simple playbook to use against.

Our first SSH Docker container

In the previous article, we installed Docker. Docker for Windows for those with Windows 10 Pro, Enterprise or Education and Docker Toolbox for the Windows 10 Home people. So we should have the docker command in the PowerShell terminal. Let's spin some machines!

Note: if the following commands are stuck or finish with something that contains error during connect is probably because Docker didn't start properly. If you have Docker Toolbox, do a docker-machine restart followed by docker-machine env | Invoke-Expression. This will reboot the VirtualBox machine and refresh your environment.

This is a basic command that will spin up an Ubuntu container, tagged as 19.04, which will run Bash at startup (/bin/bash), that will be interactive (-i), that will allocate a pseudo tty (-t), that will be named ubuntu (--name ubuntu) and that will be removed after exiting (--rm):

PS> docker run --rm -it --name ubuntu ubuntu:19.04 /bin/bash

Note that the second line starts with root@XXXXXX, so we are inside the container. You can do things, like ls or ps:

root@e491c2e0ccef:/# ps
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
   17 pts/0    00:00:00 ps
root@e491c2e0ccef:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

In this container we only have two processes running: bash, the console where we typed and ps, the one we launched. Ok, we can exit now the container using exit and start one that has SSH installed and running.

PS> docker run --rm --name sshd -d -P rastasheep/ubuntu-sshd:18.04
PS> docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
sshd    Up 8 minutes    rastasheep/ubuntu-sshd:18.04

And we can check that SSH (sshd service) is running by using the following:

PS> docker exec -it sshd ps -e
1   ?      00:00:00 sshd
97  pts/0  00:00:00 ps

Connecting with Docker for Windows

To connect to the new Docker container, we want to know it's IP. However here we have two possible scenarios: Docker Toolbox or Docker for Windwows. For the second you should get the IP the following way:

PS> docker inspect --format '{{ .NetworkSettings.IPAddress }}' sshd

That will be the IP of the Docker container itself, and you can connect it directly. In this case:

# ssh root@ContainerIP
ssh root@ # 'root' as password

Connecting with Docker Toolbox

For the scenario with Docker Toolbox, we should use the IP of the VirtualBox machine which is running the Docker containters:

PS> docker-machine ip in my case. If we try to connect doing ssh root@ we will try to connect to the SSH port of the machine, not our container. So we ran the container using -P. This flag maps the ports that the container needs to the machine, so we should know which is that port in our case:

PS> docker port sshd
22/tcp ->

The port 22 of the Docker container is mapped to the 32768 of the VirtualBox machine. So in order to connect to the container we will do:

# ssh user@VirtualBoxMachine -p PortMapped
ssh root@ -p 32768

So now you know how to connect to the machines we represented using Docker containers with SSH.

Creating the inventory

Now it is time that we use Ansible! We will need an inventory and a playbook. We will start by creating an inventory. In this case, it will be pretty small since we are only attacking one machine.

We can define variables after the IPs or for each of the groups. I personally like to have all the variables outside the inventory, since I normally create it dynamically. However if we need to specify the port for each IP, it is handy to do it here.

Again, we have here scenarios for each Docker installation.

Docker Toolbox:

[all] ansible_port=32768

Docker for Windows:


In the Docker Toolbox one, we specify the port for Ansible to connect. However, in the Docker for Windows the port is the default 22, so there is no need to specify it.

The Playbook

Now it is time for the final piece: the playbook. We will do a pretty basic one, since we are only getting started, but they will get more complicated as the series advance. For now, we have this one:

- hosts: all
    ansible_user: root
    ansible_password: root

    - name: ping

Variables can be defined inside playbooks, in a block at the hosts level called vars. These are shared by all the tasks inside the playbook, so we will be able to grab them anywhere. In our case, we only need to tell Ansible how to connect to our machines using ansible_user and ansible_password. Hardcoding these here is not a good practice and we will see a better alternative using ansible-vault. For now, we are fine harcoding them.

To run the playbook we use ansible-playbook:

ansible-playbook -i inventory playbook.yml


Now we have the basics of Ansible, with that we can move forward into more complex scenarios. We will revisiting those topics since they are the building blocks of Ansible. In the following article we will start our adventure aiming to deploy a web service, we will learn about Docker Compose and we will be launching multiple playbooks against our machines. Do not miss it!

Continue reading


Editor guide