Model – View Container

Model/View Container

This series illustrates the steps necessary to convert an automation portal to a linked, operational series of Docker Containers. The Introduction for this series is at Linked Docker Containers – TOC  

Model/View Container

This series illustrates the steps necessary to convert an automation portal to a linked, operational series of Docker Containers. The Introduction for this series is at  Linked Docker Containers – TOC.   The theory of operation of the Base automation portal is at Base Automation PortalMode/View/Controller concept is a functional decomposition of the components of a portal app.  “Model” represents the code necessary to support a web framework such as FLASK or Django and functions for operating with a database or I/O. The View is of course the HTML necessary for a web portal. The Controller is the Angularjs code necessary to receive directives from the View, which in turn will access the Model for I/O operations. 

Scope

This entry describes modifications to the Model and View components for containerization. The Model must include a web server such as Apache, Model code (Python) and a web framework process (FLASK).  The Model is responsible for making a representation of initial HTML when accessed by a web client, so the View’s HTML will be included with the containerized Model.

 

Docker

The Docker Containerization of the Model/View requires a Dockerfile, which will install all files and libraries (minus the kernel) necessary for the container to support the Model/View function in the way that hosted apps would support the same functionality. The Model/View Dockerfile is annotated as follows.  Yes, this Dockerfile has test code and a few too many update/upgrade/restart statements. Optimize your production Dockerfile for efficiency. 

 

############################################################
# Dockerfile to build python/Flask/Mongodb client container images
# Based on Ubuntu
############################################################

# Set the base image to Ubuntu
FROM ubuntu:latest                                      
Load from a local repository; Ubuntu’s files/libraries
# File Author / Maintainer
MAINTAINER  Mike Pate

# Update the repository sources list
RUN apt-get update

################## BEGIN INSTALLATION ######################
# Install Model; apps
#install curl
RUN apt-get install curl -y                              
For testing purposes
################## Python ####################
#install python 2.7
RUN apt-get install python -y                        
For Model Coding
RUN apt-get update -y
################## apache server ##############
#install apache server
RUN apt-get install apache2 -y                     
This is a Web Server, Apache becomes the Web proxy for the Python “web app”
RUN apt-get update -y
#install wsgi
RUN apt-get install libapache2-mod-wsgi python-dev -y             
Web Service Gateway Interface is required as a web framework
RUN apt-get update -y
#enable wsgi
RUN a2enmod wsgi
#
#########create directory structure########
#
RUN mkdir /var/www/ContClBase
RUN mkdir /var/www/ContClBase/ContClBase                          
Web Server HTML Base located Here
RUN mkdir /var/www/ContClBase/ContClBase/static                 
js code located here
RUN mkdir /var/www/ContClBase/ContClBase/templates          
portal HTML code located here
#
##############copy Flask App to Container ###########
COPY MyContainerCl.py  /var/www/ContClBase/ContClBase/MyContainerCl.py           
Model Code
COPY sandbox5.html /var/www/ContClBase/ContClBase/templates/sandbox5.html      
HTML file
RUN chmod +x /var/www/ContClBase/ContClBase/MyContainerCl.py
############  Virtual env #####################
#
RUN apt-get install python-pip -y
RUN apt-get update -y
###   RUN source venv/bin/activate  but not yet
#############   Flask ##########################
RUN pip install Flask                                                                                                      
Web Framework
#
#install additional Flask, Bower, Mongo components
RUN pip install flask-bower
RUN pip install pymongo                                                                                               
Supports Mongo import for Python
# Update the repository sources list once more
RUN apt-get update -y
################ copy virtual host config file to container ########
COPY MyContainerCl.conf /etc/apache2/sites-available/MyContainerCl.conf             
The virtual host file identifies the wsgi file to Apache for proxying
#############enable virtual host #################
RUN a2ensite MyContainerCl                                                                                        
enable Apache to proxy the MyContainerCl.com site as set up in the virtual host file below
# copy the  wsgi file into the container  ############
COPY FlaskApp.wsgi /var/www/ContClBase/FlaskApp.wsgi                                        
Instantiates a Python app as a native web app
# copy hosts file additions  to /etc/hosts                                                                        
any additional hosts declarations
COPY hosts /var/www/ContClBase/ContClBase/hosts
# expose port 80, since pirt 80 is the server port as identified in teh FlaskApp.conf
EXPOSE 80                                                                                                                  
matches port in MyContainerCl.conf
# copy cmd wrapper  script containing copying of host file info plus  python script
COPY wrapper.sh wrapper.sh
####  restart apache ############
# RUN service apache2 restart
RUN apt-get upgrade -y
# Set default container command
# ENTRYPOINT /bin/bash
# CMD cat /var/www/ContClBase/ContClBase/hosts >> /etc/hosts; python /var/www/ContClBase/ContClBase/hello_world.py
CMD ./wrapper.sh                                                                                                        
will restart Apache and start Python/Flask app

 

​Model (Python) Code revisions

 

Some Model coding must change in order to support the MongoDB residing in a separate container, including its own (Docker br0) assigned IP address. This is the only change necessary for the original Python code, where the MongoDB referene is  a host reference to the ip address of the MongoDB container as follows. The original code can be found at Python Code

client = MongoClient(“mongodb://MongoDB”)  instead of the original “client = MongoClient()” reference to a local DB

 

View Code Changes

As mentioned, the View HTML code resides on the same container as the Model Code.  The view HTML and Angularjs directives do not change.  HTML link references to CSS and js files change so as to point to files located in the Controller container. The original code can found at Code Review.

 

    <!– Bootstrap –>

    <!link href=”static/js/bootstrap.tmp.css” rel=”stylesheet”>

    <link href=”http://mpates-scripts.com/bower_components/bootstrap/dist/css/bootstrap.min.css” rel=”stylesheet”>

    <link href=”http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css” rel=”stylesheet”>

    <link rel=”stylesheet” href=”https://www.w3schools.com/w3css/4/w3.css“>

</head>

 |

 |   original HTML body would fill in here

\/

    <!script src=”https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js“></script>

    <!– Include all compiled plugins (below), or include individual files as needed –>

    <script type=”text/javascript” src=”http://mpates-scripts.com/bower_components/angular/angular.min.js“></script>

    <script type=”text/javascript” src=”http://mpates-scripts.com/bower_components/jquery/dist/jquery.min.js“></script>

    <script type=”text/javascript” src=”http://mpates-scripts.com/bower_components/bootstrap/dist/js/bootstrap.min.js“></script>

    <script type=”text/javascript” src=”http://mpates-scripts.com/bower_components/bootstrap-css/css/bootstrap-theme.min.css“></script>

    <script type=”text/javascript” src=”http://mpates-scripts.com/bower_components/ng-ip-address/ngIpAddress.min.js“></script>

    <script type=”text/javascript” src=”http://mpates-scripts.com/app-ip.js“></script>

    <script type=”text/javascript” src=”http://mpates-scripts.com/announce_prefix3.js“></script>

</body>

 

FlaskApp.wsgi

This file is necessary to employ FLASK in associating the Python app as a native web app.

#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.append(‘/var/www/ContClBase/ContClBase/’)                   include the app HTML root in the environment
from MyContainerCl import app as application                                 
from MyContainerCl {python file minus “py” extension), import the Python code as an application 

 

MyContainerCl.conf

 

This file is necessary to configure Apache to proxy connections on behalf of FLASK.  This is the “virtual host file” allowing Apache to represent (proxy) MyContainer.Cl (Python/FLASK app) as a web site:

 

<VirtualHost *:80>                                                                        port that should be “exposed” in Dockerfile
ServerName MyContainerCl.com                                              
host identity for server to Proxy for wsgi
ServerAdmin root@MyContainerCl.com                                   
“root” is default container user, setup here to receive emails
WSGIScriptAlias / /var/www/ContClBase/FlaskApp.wsgi          
FLASK reference file
<Directory /var/www/ContClBase/ContClBase/>                       
indeed the base HTML directory
Order allow,deny                                                                      
access control to MyContainerCl.com root HTML dir ; effectively Allow from ALL
Allow from all
</Directory>
Alias /static /var/www/ContClBase/ContClBase/static              
alias for location of js files
<Directory /var/www/ContClBase/ContClBase/static/>
Order allow,deny                                                                     
access control to static dir (js files);effectively Allow from All
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
< /VirtualHost>

 

Wrapper.SH

This file is necessary to start require processes.  The Model is a web server that requires Python as a “web app”

#!bin/bash
service apache2 restart
python /var/www/ContClBase/ContClBase/MyContainerCl.py &
/bin/bash

 

Summary

The Dockerfile,when executed will launch the container, as named in the “docker” command string. When the container starts running, it will execute the contents of ” CMD ./wrapper.sh” (end of the Dockerfile). Apache will restart and MyContainerCl will launch as a FLASK enabled web service. The base HTML (below) referenced by MyContainerCl.py statements will be made available as the “View” to a client browser. Bear in mind that until the Controller (Angularjs) container is launched, none of the angular directives in the HTML view will be executed.

“def main():

    return render_template(‘sandbox5.html’) “