Deploy and Configure the Provided Application Back End with a Provided Custom Docker Image

1.5 hours
  • 5 Learning Objectives

About this Hands-on Lab

The objective of this lab is to deploy and configure the provided application back end with a database and Apache reverse proxy. We need to create a custom image for the provided Python Flask application. Then we will need to create an image of the database which this application will use. After that, we have to configure the Apache web server reverse proxy through which the back-end Python application will be accessible. Lastly, it is required to install and set up a firewall.

Learning Objectives

Successfully complete this lab by achieving the following learning objectives:

Create an Image for Our Python Flask Back-End Application

Create a Dockerfile

vim /home/cloud_user/Dockerfile
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /

LABEL org.label-schema.schema-version="1.0" 
    org.label-schema.name="CentOS Base Image" 
    org.label-schema.vendor="CentOS" 
    org.label-schema.license="GPLv2" 
    org.label-schema.build-date="20191001"

RUN yum -y update
RUN yum install -y python36 python36-devel
RUN pip3 install flask flask_cors
RUN yum install -y mariadb-devel gcc
RUN pip3 install flask_mysqldb
RUN pip3 install mysql-connector
RUN mkdir /app

COPY app.py /app
WORKDIR /app

ENTRYPOINT ["python3"]
CMD ["app.py"]
EXPOSE 65535
ESC
:wq
ENTER

Create Our Back-End App

vim /home/cloud_user/app.py
from flask import Flask
from flask_cors import CORS
import mysql.connector as mariadb

import random
import hashlib
import json

app = Flask(__name__)
CORS(app)

@app.route("/")
def initialTest():
        return "TEST"

@app.route("/youtube_video")
def youtube_video():
        base_url = "https://www.youtube.com/embed/"
        video_ids = [   "h8xYLsmGnEQ",
                        "wZ31Tk2OxyE",
                        "6_IGyMM3QKE",
                        "E7WKVMkF98Q",
                        "g8kJnFTz87M",
                        "ADvYULvHs6Y",
                        "hA-onpcn__8",
                        "WBFb5x6g4dA",
                        "1PPGUOBzzKY",
                        "8xjBwTq2Dss",
                        "iI-cAtKgPXs",
                        "piu-TK00j_c",
                        "7te-pqNAl4o",
                        "s9_L_6r1Eh4",
                        "PZs7MImMOy8",
                        "LJi1FXLINgA",
                        "sGOlcIVd4Dw",
                        "h7a4ATtwkGI",
                        "4bSNfzucG8A"   ]
        return '<iframe src="' + base_url + video_ids[random.randint(0,18)] + '"></iframe>'

@app.route("/random_number")
def random_number():
        return hashlib.sha224(str(random.randint(1, 10149583095834095834059349)).encode()).hexdigest()

@app.route("/motd")
def motd():
        mariadb_connection = mariadb.connect(user='chronic', password='Test321', database='MyDB')
        cursor = mariadb_connection.cursor()
        cursor.execute("SELECT msg FROM motd;")

        msg = cursor.fetchall()[random.randint(0,8)][0]
        mariadb_connection.commit()

        cursor.close()

        return str(msg)

@app.route("/set_motd")
def set_motd():
        msg1 = "Whoever said that the definition of insanity is doing the same thing over and over again and expecting different results has obviously never had to reboot a computer."
        msg2 = "Programmer’s girlfriend: Are you going to sit and type in front of that thing all day or are you going out with me?nProgrammer: Yes."
        msg3 = "What do you call 8 hobbits?nA hobbyte"
        msg4 = "How many programmers does it take to change a light bulb?nNone. It's a hardware problem."
        msg5 = "I broke my finger last week. On the other hand I'm ok."
        msg6 = "What did the computer do at lunchtime?nHad a byte"
        msg7 = "Once a programmer drowned in the sea. Many Marines where at that time on the beach, but the programmer was shouting F1 F1 and nobody understood it."
        msg8 = "Unix is user friendly. It's just very particular about who it's friends are.""
        msg9 = "How many software testers does it take to change a light bulb?nNone. We just recognized darkness, fixing it is someone else's problem."

        messages = [msg1, msg2, msg3, msg4, msg5, msg6, msg7, msg8, msg9,]

        mariadb_connection = mariadb.connect(user='chronic', password='Test321', database='MyDB')
        cursor = mariadb_connection.cursor()

        counter = 0
        for m in messages:
                cursor.execute("INSERT INTO motd(msg) VALUES(%s);", (messages[counter],))
                counter += 1

        mariadb_connection.commit()
        cursor.close()

        return "DONE"

if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0',port=65535)
ESC
:wq
ENTER

Build an Image Out Of a Docker File

sudo docker build -t cloud_user/flask-app:v1 .

Run Our Container

sudo docker run -d --restart=always --network=host -p 65535:65535 cloud_user/flask-app:v1
Create an Image for Our Database and Run the Container
vim myDB.sh
docker container run 
        --name sql-maria 
        -e MYSQL_ROOT_PASSWORD=!!!Test321!! 
        -e MYSQL_USER=chronic 
        -e MYSQL_PASSWORD=Test321 
        -e MYSQL_DATABASE=MyDB 
        -p 3306:3306 
        -d mariadb:10
ESC
:wq
ENTER

Change File to Be Executable

chmod 700 myDB.sh

Run Our Container

sudo ./myDB.sh

Create an Image Out of Our Container

sudo docker commit -a chronic -m my_sql_img CONTAINER_ID chronic/my_sql_img:v1

Stop Initial Container

sudo docker stop sql-maria

Create Storage Volume for Our Database

mkdir database

Start a New Container in the Background from the Image We Created

sudo docker run -d --restart=always -p 3306:3306 -v /home/cloud_user/database:/var/lib/mysql/:Z chronic/my_sql_img:v1
Install and Configure Apache Web Server Reverse Proxy to Point to Our Back-End App

Install httpd

sudo yum install httpd
sudo systemctl start httpd
sudo systemctl enable httpd

Create Needed Directories

sudo mkdir /etc/httpd/sites-enabled
sudo mkdir /etc/httpd/sites-available

Inform Apache of the New Directories

sudo vim /etc/httpd/conf/httpd.conf
IncludeOptional sites-enabled/*.conf
ESC
:wq
ENTER

Get Public Hostname

curl -s http://169.254.169.254/latest/meta-data/public-hostname

Create a Configuration for a Virtual Host Reverse Proxy

sudo vim /etc/httpd/sites-available/[public hostname].conf
<VirtualHost *:80>
    ServerName www.[public hostname]
    ServerAlias [public hostname]

    DocumentRoot /var/www/html

    ProxyPass          /    http://127.0.0.1:65535/
    ProxyPassReverse   /    http://127.0.0.1:65535/

    <Proxy http://127.0.0.1:65535/>
            Require all granted
            Options None
    </Proxy>
</VirtualHost>
ESC
:wq
ENTER
sudo ln -s /etc/httpd/sites-available/[public hostname].conf /etc/httpd/sites-enabled/[public hostname].conf
sudo systemctl restart httpd
Configure firewalld
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --reload
Run Tests and Verify It All Works

Install MySQL Client

sudo yum install mariadb

Connect to the Database

mysql -h 127.0.0.1 -p -u chronic MyDB

Create a Table

create table motd(msg VARCHAR(200));

Exit Database

exit

Send the Following Requests in a Browser

http://SERVER_PUBLIC_IP/random_number
http://SERVER_PUBLIC_IP/youtube_video
http://SERVER_PUBLIC_IP/set_motd
http://SERVER_PUBLIC_IP/motd

Additional Resources

The Python Flask app source code is located in the git repo here: https://github.com/ErminLA/Containers.git

Clone it:

sudo yum install git -y
cd /home/cloud_user/
git clone https://github.com/ErminLA/Containers.git
mv /home/cloud_user/Containers/app.py /home/cloud_user/

What are Hands-on Labs

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Sign In
Welcome Back!

Psst…this one if you’ve been moved to ACG!

Get Started
Who’s going to be learning?