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 Portal. Mode/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’) “