This article describes how to build Docker image and deploy containerized application on Atomic host (any Remote host) using Ansible Playbook.
Building Docker image for an application and run container/cluster of containers is nothing new. But the idea is to automate the whole process and this is where Ansible playbooks come in to play.
Note that you can use Cloud/Workstation based Image to execute the following task. Here I am issuing the commands on Fedora Workstation.
Let’s see How to automate the containerization and deployment process for a simple Flask application:
We are going to deploy container on Fedora Atomic host.
First, Let’s Create a simple Flask Hello-World Application.
This is the Directory structure of the entire Application:
flask-helloworld/
├── ansible
│ ├── ansible.cfg
│ ├── inventory
│ └── main.yml
├── Dockerfile
└── flask-helloworld
├── hello_world.py
├── static
│ └── style.css
└── templates
├── index.html
└── master.html
hello_world.py
from flask import Flask, render_template
APP = Flask(__name__)
@APP.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
APP.run(debug=True, host='0.0.0.0')
static/style.css
body {
background: #F8A434;
font-family: 'Lato', sans-serif;
color: #FDFCFB;
text-align: center;
position: relative;
bottom: 35px;
top: 65px;
}
.description {
position: relative;
top: 55px;
font-size: 50px;
letter-spacing: 1.5px;
line-height: 1.3em;
margin: -2px 0 45px;
}
templates/master.html
<!doctype html>
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %}</title>
{% endblock %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link href='http://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
</head>
<body>
<div id="container">
{% block content %}
{% endblock %}</div>
</body>
</html>
templates/index.html
{% extends "master.html" %}
{% block title %}Welcome to Flask App{% endblock %}
{% block content %}
<div class="description">
Hello World</div>
{% endblock %}
Let’s write the Dockerfile.
FROM fedora
MAINTAINER Trishna Guha<tguha@redhat.com>
RUN dnf -y update && dnf -y install python-flask python-jinja2 && dnf clean all
RUN mkdir -p /app
COPY files/ /app/
WORKDIR /app
ENTRYPOINT ["python"]
CMD ["hello_world.py"]
Now we will work on Ansible playbook for our application that deals with the automation part:
Create inventory file:
[atomic]
IP_ADDRESS_OF_HOST ansible_ssh_private_key_file=<'PRIVATE_KEY_FILE'>
Replace IP_ADDRESS_OF_HOST with the IP address of the atomic/remote host and ‘PRIVATE_KEY_FILE’ with your private key file.
Create ansible.cfg file:
[defaults]
inventory=inventory
remote_user=USER
[privilege_escalation]
become_method=sudo
become_user=root
Replace USER with the user of your remote host.
Create main.yml file:
---
- name: Deploy Flask App
hosts: atomic
become: yes
vars:
src_dir: [Source Directory]
dest_dir: [Destination Directory]
tasks:
- name: Create Destination Directory
file:
path: "{{ dest_dir }}/files"
state: directory
recurse: yes
- name: Copy Dockerfile to host
copy:
src: "{{ src_dir }}/Dockerfile"
dest: "{{ dest_dir }}"
- name: Copy Application to host
copy:
src: "{{ src_dir }}/flask-helloworld/"
dest: "{{ dest_dir }}/files/"
- name: Make sure that the current directory is {{ dest_dir }}
command: cd {{ dest_dir }}
- name: Build Docker Image
command: docker build --rm -t fedora/flask-app:test -f "{{ dest_dir }}/Dockerfile" "{{ dest_dir }}"
- name: Run Docker Container
command: docker run -d --name helloworld -p 5000:5000 fedora/flask-app:test
...
Replace [Source Directory]
in src_dir
field in main.yml with your /path/to/src_dir
of your current host.
Replace [Destination Directory]
in dest_dir
field in main.yml with your /path/to/dest_dir
of your remote atomic host.
Now simply run $ ansible-playbook main.yml :). To verify if the application is running issue this command $ curl http://localhost:5000 on your atomic/remote host.
You can also manage your containers running on remote host using Cockpit. Check this article to know how to use Cockpit to manage your containers: https://fedoramagazine.org/deploy-containers-atomic-host-ansible-cockpit
Here is the repository of the above example: https://github.com/trishnaguha/fedora-cloud-ansible/tree/master/examples/flask-helloworld
My future post will be related to ansible-container where I will describe how we can build Docker image and orchestrate container without writing any Dockerfile :).
Like my blog? You know what to do!