Retrieving Container’s IP Dynamically Using Ansible and Configuring a Webserver Inside the Container

Hey guys hope you all are doing in today’s article we are going to see how can we directly run ansible-playbook directly into the docker container. Isn’t it interesting just think one playbook launching container for us updating inventory and when we run another playbook it will configure the container to run an apache web server.

Ansible is used for automation, but certain things are still done manually inside Ansible too and they need to be automated as well. One such element is the inventory of Ansible. Sometimes, we create and update the inventory manually while the other times, we want it to be dynamic i.e, it should gather all the hosts over a platform dynamically.

In this blog, I will be creating an Ansible playbook that will launch a container, retrieve the IP of that container and update it in the inventory at the same moment. And in the next playbook ( or in the same one), we can further proceed to go inside that container to perform certain configurations.

Most of the time, Ansible uses the SSH protocol to go inside a Linux system for configuration management. Similarly, to go inside the docker container as well, Ansible needs an SSH connection with the container. Here, I will be using ‘CentOs’ as the base image and by default, SSH is not enabled inside this image.

To continue with this practical we will be needed a docker image that has ssh enabled in it .Once you have an image with ssh enabled we are ready to write the playbook we are going to write two playbook one for launching container and updating inventory and one for configuring container.

So, my first step would be creating an SSH enabled image.

I am going to use the above Dockerfile to create an SSH enabled image:

To build the image:

And hence, the SSH enabled image has been created:

Now, the next part is to create an Ansible playbook that will launch the container, retrieve its IP, and update the IP in the inventory dynamically.

- name: Docker
  hosts: localhost
  vars_prompt:
    - name: container
      prompt: Enter Container Name
      private: no
    - name: port1
      prompt: Enter The Exposed Port For Webserver
      private: no
    - name: port2
      prompt: Enter The Exposed Port For SSH
      private: no
  tasks:
    - name: Starting Docker Daemon
      service:
        name: docker
        state: started
    - name: Launching Container
      docker_container:
        name: “{{ container }}”
        image: docker_ssh:v1
        state: started
        interactive: yes
        tty: yes
        ports:
         - “{{ port1 }}:80”
          - “{{ port2 }}:22”
      register: x
    - name: debugging
      debug:
        var: x.container.NetworkSettings.IPAddress
    - name: Updating Inventory
      blockinfile:
        path: file.txt
        block: |
                [docker]
                {{ x[‘container’][‘NetworkSettings’][‘IPAddress’] }} ansible_ssh_user=root ansible_ssh_pass=docker ansible_connection=ssh

This playbook will ask for the container name, the exposed ports for SSH and WebService and then it will launch the container from the given image (the same image we created in the above step).

After launching, it will register the output in a variable named ‘x’. Then it will retrieve the IP of the container for the variable and update it in a file called ‘file.txt’.

In above playbook test can be changed to any name as you like want to launch the container. An image I have used my image you can either use this or you can create your own and update in the playbook accordingly.

This ‘file.txt’ file will be our inventory file and we have to pass this file in the configuration file of Ansible.
Here is an ‘ansible.cfg’ file I have created locally:

Now, let’s run this playbook using command:

“ansible-playbook docker.yml”

Here you can see that container has been launched.

Here, you can see that the IP of the container has been retrieved. I have export port 22 of the container because we can do SSH inside the container in two ways:

 First, by using the Base OS’s IP and port 9002, in this case, we can run Ansible on some other node, that node will come to this Base OS and it will configure the container running on this OS using the exposed SSH port.

Or, by using the IP of the container and port 22, if the OS has direct connectivity with the containers, and in this case, we have to run the Ansible on the localhost only.

For convenience, I am using the second option. However, you can go for any of the above methods. If you go for the first option, you have to use port 5002 for SSH instead of port 22. 

And as you can see, the inventory has been updated as well.

The next step is configuring something (let’s configure a webserver) by going inside the container and this thing will be done by Ansible only.

Here, is the Ansible playbook for the same.

- hosts: docker
  tasks:
    - name: Installing webseerver
      package:
        name: httpd
        state: present
    - name: Configuring the webpages
      copy:
        content: "HELLO FROM DOCKER"
        dest: /var/www/html/index.html
    - name: Starting the service
      command: "/usr/sbin/httpd"

As we know that we can’t use ‘systemctl’ command to start the service inside the container. So here, I have directly executed the binary of ‘httpd’ to start the service.

Here is the output of the playbook:

The playbook ran successfully. Let’s try to access the webpage at port 5002 of Base OS:

And hence, we have successfully configured a web server as well by going inside the container using Ansible.

#BONUS

We have one more way of doing the same i.e, getting the IP of the container dynamically. This can be done by using a script, generally called a dynamic inventory.

You can either create a script in any of the languages to retrieve the IP or you can use some pre-created scripts. You can get some pre-created dynamic inventory scripts at this location.

Here, we need two files: docker.py and docker.yml.

Download both the files in your local system. You need to make the python file executable by using the ‘chmod +x docker.py’ command.

You just have to change the ‘env python’ to ‘python3’ in the first line of the docker.py file:

And now, all you need to do is to execute the file to get the information about the running containers. But before that, let’s launch some containers:

And now, let’s execute the script:

As you can see, it will give you the entire info about all the containers.

But now the question arises, how to use this inventory? So, in the configuration file of Ansible, we can directly pass this file to get the hosts:

To retrieve the hosts:

And hence, you can see that all the hosts have been retrieved successfully using the dynamic inventory script of docker.



Categories: DevOps

Tags: , , , , , , ,

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: