In this blog, I will deploy FLASK app on nginx using Docker Compose. If you don’t have any idea how Docker Compose works, read my previous blog first (Click here to read the previous blog).
Before we move to work, I will give you brief intro the things which I am going to use. I created a virtual machine on Azure Cloud Platform. If you don’t know, how to create virtual machine on Azure, go to my this blog create virtual machine easily with few simple steps (Click here to read the blog).
After creating virtual machine just ssh into your machine using simple command.
ssh halcyoona@40.114.31.5
Installation
To install Docker the in your virtual machine, type the command in terminal and press enter:
sudo apt install docker.io sudo apt install docker-compose
Create a directory with the name of your app, like I am creating my_flask_app.
mkdir my_flask_app cd my_flask_app
In this floder create two more directory with the nginx and flask. Nginx is entry point of the app, where we get request and then we redirect those request to flask app.
mkdir flask mkdir nginx
Flask App Setting
Now move into flask directory and create python virtual environment but first install package that is required to create the virtual environment i.e venv first then create virtual environment using following command:
cd flask sudo apt install python3-venv python3 -m venv env
Now activate the environment with the simple command:
soure env/bin/activate
And then install flask and uwsgi.
pip install flask uwsgi
flask package is used to create the applications.
uwsgi is a Web Server Gateway Interface used to communicate to nginx server.
Check the packages installed in the environment.
pip list
Output will be this:
click (7.1.2) Flask (1.1.2) itsdangerous (1.1.0) Jinja2 (2.11.2) MarkupSafe (1.1.1) pip (9.0.1) pkg-resources (0.0.0) setuptools (39.0.1) uWSGI (2.0.19.1) Werkzeug (1.0.1)
Now create the file with name run.py and write this code into this file. This is the file which run your application.
touch run.py
And then write this code
from app import app
if __name__ == "__main__":
app.run()
Now create the directory with the name app and inside it create two files with the name __init__.py and views.py
mkdir app cd app touch __init__.py touch views.py
In __init__.py, write this code.
from flask import Flask
app = Flask(__name__)
from app import views
__init__.py is the file which runs first when your application starts.
In views.py. Write your code but I am creating simple helloworld.
from app import app
@app.route("/")
def index():
return "Hello from Flask App"
views.py is the file in which you wrtie code for application i.e you make different pages and include those pages to views… etc.
Now we need create the requirements file which contains all the packages that is installed in the environment. Because we don’t want to write every command in Dockerfile and sometimes we forget packages and this make trouble as well.
just run this command and get requirements and include this file in Dockerfile and that’s it and all your packages will be install. First move to back to your flask directory Because we are in /flask/app.
cd .. pip freeze > requirements.txt
Now create .dockerignor file to specify the things which you want docker to be ignor and don’t not include those in things in container.
touch .dockerignor
And write this code in this file.
env/ __pycache__/
Now move to the most important file that is Dockerfile create the Dockerfile.
touch Dockerfile
And write the following code inside the Dockerfile.
#Use the python3.7.2 image and create the container with that image.
FROM python:3.7.2-stretch
#Set the working Directory in the container
WORKDIR /app
#copy the current directory contents into container at /app. In this '.' means current directory content and move to /app in the container
ADD . /app
#Install the dependencies in the container
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
RUN pip install uWSGI
#Run the command to start uWSGI in the container
CMD ["uwsgi", "app.ini"]
You can easily get what is written in the file with comments.
Now create the file app.ini inside the flask directory and app.ini file is configuration file and you can check different configuration on uWSGI site.
cd flask touch app.ini
And write this code in this file.
[uwsgi]
wsgi-file = run.py
callable = app
socket = :8000
processes = 4
threads = 2
master = true
chmod-socket = 660
vacuum = true
die-on-term = true
wsgi-file= run.py -> we have to specify the file which is used to run the application.
callable= app -> we have callable app in run.py so that’s why we use app as callable.
socket= :8000 -> This is listening on port 8000 from any IP address.
Nginx Setting
Now move to nginx directory. And create the nginx.conf. This contains the configuration setting for nginx.
touch nginx.conf
Write this code in this file.
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass flask:8000;
}
}
This server is listening on port 80. Actually we are redirecting request to flask using uwsgi_params. And you can see we use port 8000 to communicate Because in uwsgi configuration file we use port 8000.
Docker Compose create a network and made it very easy to communicate with different containers in the network and you should set the host name of the container to the name of your service and then this make it more easy.
As in the above we called flask container which is listening on port 8000. Because flask is host name of the container we are going to define in later in docker-compose.yml.
Now create the Dockerfile for nginx.
touch Dockerfile
And write this code in this file.
#Use the nginx Image and create the container from the Image
FROM nginx
#Remove the default nginx.conf
RUN rm /etc/nginx/conf.d/default.conf
#Replace with our own nginx.conf
COPY nginx.conf /etc/nginx/conf.d/
Docker Compose Setting
Now move to my_flask_app directory. And create the file docker-compose.yml.
touch docker-compose.yml
And write this code in it.
version: "2.2"
services:
flask:
build: ./flask
container_name: flask
restart: always
environment:
- APP_NAME=MyFlaskApp
- DB_USERNAME=example
expose:
- 8000
nginx:
build: ./nginx
container_name: nginx
restart: always
ports:
- "80:80"
build:./flask -> This is actually looking for a flask directory in the current directory and then run the Dockerfile inside the flask directory.
container_name: flask -> assigning host name to the container.
expose: 8000 -> Exposing port 8000 to other containers.
ports: “80:80” -> mapping host operating system port to containers port. The request comes to over virtual machine on port 80 goes to the nginx container port 80 and then nginx redirect it to flask container.
Running Docker Compose
Now every thing is complete and move to build.
sudo docker-compose build
It’s good to watch the output which packages are installing.
Building flask
Step 1/7 : FROM python:3.7.2-stretch
3.7.2-stretch: Pulling from library/python
e79bb959ec00: Pull complete
d4b7902036fe: Pull complete
1b2a72d4e030: Pull complete
d54db43011fd: Pull complete
69d473365bb3: Pull complete
7dc3a6a0e509: Pull complete
a288a79001c3: Pull complete
7d3cdae56021: Pull complete
dbf17696f820: Pull complete
Digest: sha256:a67ce4c774591f13500901fd4061e0c96a274c1e88fa8f6a96efaa983ae9c203
Status: Downloaded newer image for python:3.7.2-stretch
Step 2/7 : WORKDIR /app
---> Using cache
---> a2c58f6f2a90
Step 3/7 : ADD . /app
---> 59ff085f8e6c
Step 4/7 : RUN pip install --upgrade pip
---> Running in 12544c84d3f7
Collecting pip
Downloading https://files.pythonhosted.org/packages/43/84/23ed6a1796480a6f1a2d38f2802901d078266bda38388954d01d3f2e821d/pip-20.1.1-py2.py3-none-any.whl (1.5MB)
Installing collected packages: pip
Found existing installation: pip 19.0.3
Uninstalling pip-19.0.3:
Successfully uninstalled pip-19.0.3
Successfully installed pip-20.1.1
Removing intermediate container 12544c84d3f7
---> 88502a46901b
Step 5/7 : RUN pip install -r requirements.txt
---> Running in 917442f8ebf3
Collecting click==7.1.2
Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Flask==1.1.2
Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting itsdangerous==1.1.0
Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2==2.11.2
Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting MarkupSafe==1.1.1
Downloading MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl (27 kB)
Collecting Werkzeug==1.0.1
Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Installing collected packages: click, Werkzeug, MarkupSafe, Jinja2, itsdangerous, Flask
Successfully installed Flask-1.1.2 Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 itsdangerous-1.1.0
Removing intermediate container 917442f8ebf3
---> bc5156d8e278
Step 6/7 : RUN pip install uWSGI
---> Running in 4a028bae390c
Collecting uWSGI
Downloading uWSGI-2.0.19.1.tar.gz (803 kB)
Building wheels for collected packages: uWSGI
Building wheel for uWSGI (setup.py): started
Building wheel for uWSGI (setup.py): finished with status 'done'
Created wheel for uWSGI: filename=uWSGI-2.0.19.1-cp37-cp37m-linux_x86_64.whl size=595659 sha256=89886458bfd5a67dd2693f4d1e3a56917c494f8f237f0393c4994d62316ecede
Stored in directory: /root/.cache/pip/wheels/0c/f9/df/fb7fb12204a8f5c67682f31e10485863c24123a2a626e71203
Successfully built uWSGI
Installing collected packages: uWSGI
Successfully installed uWSGI-2.0.19.1
Removing intermediate container 4a028bae390c
---> 1ed5b7818c52
Step 7/7 : CMD ["uwsgi", "app.ini"]
---> Running in b6683d9e1ce3
Removing intermediate container b6683d9e1ce3
---> a749b9c5fab8
Successfully built a749b9c5fab8
Successfully tagged myflaskapp_flask:latest
Building nginx
Step 1/3 : FROM nginx
latest: Pulling from library/nginx
8559a31e96f4: Pull complete
1cf27aa8120b: Pull complete
67d252a8c1e1: Pull complete
9c2b660fcff6: Pull complete
4584011f2cd1: Pull complete
Digest: sha256:a93c8a0b0974c967aebe868a186e5c205f4d3bcb5423a56559f2f9599074bbcd
Status: Downloaded newer image for nginx:latest
---> 0901fa9da894
Step 2/3 : RUN rm /etc/nginx/conf.d/default.conf
---> Running in bba46218a4e2
Removing intermediate container bba46218a4e2
---> 9249b1579938
Step 3/3 : COPY nginx.conf /etc/nginx/conf.d/
---> 7746a1467014
Successfully built 7746a1467014
Successfully tagged myflaskapp_nginx:latest
This will build the containers and set the environment. And you can see every step that Docker Compose takes.
Now Run the environment.
sudo docker-compose up
Now open the browser on any machine access the IP address of your virtual machine you will get this on your browser.
That’s it for now. In next blog I am going to add database in this project making link between database and flask.
[…] If you want to deploy a website using Docker Compose check out my blog on deployment (Click here to go to deployment blog). […]
LikeLike