Launch Web server with Docker and Ansible automation

Launch Web server with Docker and Ansible automation

Have you ever wanted to Launch multiple webservers with just one click? If yes, Ansible and docker are the solutions. Ansible has builtin docker modules which help to control containers of the managed nodes. So you can start a production server with ansible and docker by adding a reverse proxy server like Haproxy. Haproxy has to wait for now because we will be focusing on httpd server creation on docker for now.

First, make sure you have added inventory files to the ansible.cfg file

ansible.cfg file:

[defaults]
inventory = /etc/ansible/hosts
remote_user=root
host_key_checking=False

Then we need to add the inventory file with the IP we want to work with and the password of the SSH user

[dockerhttpd]
192.168.226.132 ansible_ssh_password=<ssh_password>

After this, we write an ansible playbook as a YAML file.

  • First, we add YUM repo using yum_repository module
- name: configure yum
   yum_repository:
     name: docker-ce2
     description: to install docker
     baseurl: https://download.docker.com/linux/centos/7/x86_64/stable/
     gpgcheck: no
  • Then we need to install Docker in the system. Here I have used shell because I am using Docker in Red Hat. But if you are working with another os, you can use the package module to install it
  - name: install docker
    shell: "yum install docker-ce --nobest -y"
  • Then we need python to be installed in the Managed node. We need python to use the docker commands with the help of docker.py module for automation of docker

  • we use pip module to install the docker module

 - name: install python3
   package:
      name: python3
      state: present

 - name: start docker
   service:
      name: docker
      state: started
  • then we create a directory where we store the index.html files and then mount it to the container

The reason why I am mounting the directory is that ansible docker module hasn't created a copy module because copying to ephemeral is not an advisable task.

  • Then we need to copy the index.html file to the host os and store it in /websrc/ location which we will mount to /var/www/html inside the container.
 - name: create directory to store files
   file:
      path: "{{ pathmount }}"
      state: directory

 - name: copy files to host os
   copy:
      src: ./index.html
      dest: "{{ pathmount }}"
  • After this, we start the docker container with opening the 80 port to another random port and then mount the /websrc in base OS to /var/www/html inside the container. Here I used the centos/httpd image to launch the httpd server.
 - name: start container
   docker_container:
      name: webserver
      image: centos/httpd
      ports:
          - "80"
      mounts:
          - source: "{{ pathmount }}"
            target: /var/www/html
            read_only: yes
            type: bind
    register: result

This is the output we get when we request to the IP

Output value

The whole working Code:

- hosts: dockerhttpd
  vars:
    pathmount: /websrc/
  tasks:
    - name: configure yum
      yum_repository:
        name: docker-ce2
        description: to install docker
        baseurl: https://download.docker.com/linux/centos/7/x86_64/stable/
        gpgcheck: no

    - name: install docker
      shell: "yum install docker-ce --nobest -y"

    - name: install python3
      package:
        name: python3
        state: present

    - name: start docker
      service:
        name: docker
        state: started

    - name: install docker python package
      pip:
        name: docker

    - name: create directory to store files
      file:
        path: "{{ pathmount }}"
        state: directory

    - name: copy files to host os
      copy:
        src: ./index.html
        dest: "{{ pathmount }}"

    - name: start container
      docker_container:
        name: webserver
        image: centos/httpd
        ports:
          - "80"
        mounts:
          - source: "{{ pathmount }}"
            target: /var/www/html
            read_only: yes
            type: bind
      register: result

    - name: print port
      debug:
        msg: "192.168.226.132:{{result.container.NetworkSettings.Ports['80/tcp'][0].HostPort}}"

Hope you have enjoyed this post and a big thanks to Vimal Daga sir for making this article possible