Building a minimalist Flask + uWSGI + Vue.js + Nginx app
with docker deployment
keep it to a good practice as possible.
Chapter 1. Backend (Flask + uWSGI)
- First, establish a virtual environment use pipenv.
mkdir backend
pipenv shell`
pipenv install flask, uWSGI
- Second, create a bare minimal flask app named as
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == "__main__":
app.run(host='0.0.0.0')
- Third, create a
wsgi.py
from app import app
if __name__ == "__main__":
app.run()
- Lastly, create a
app.ini
file for uWSGI configs
[uwsgi]
# the module itself, by referring to the wsgi.py file minus the extension, and the callable within the file, app:
module = wsgi:app
# Enable hot reload!
py-autoreload = 1
# Nginx to handle actual client connections, which will then pass requests to uWSGI.
socket = :8080
master = true
processes = 4
threads = 2
# giving the Nginx group ownership of the uWSGI process later on,
# so we need to make sure the group owner of the socket can read information from it and write to it.
chmod-socket = 660
# clean up the socket when the process stops by adding the vacuum option:
vacuum = true
die-on-term = true
- After all of this, our python backend is ready, create a requirements.txt by
pipenv lock -r > requirements.txt
- Now we just need to create a docker file, which will copy files and then install necessary libraries (as outlined in requirements.txt) and get our uWSGI server up and running.
# use python container image
From python:3.6-stretch
# set the working directory of the image filesystem
WORKDIR /backend
# copy current directory to the working directory
ADD . /backend
# Install the python dependencies
RUN pip install -r requirements.txt
# start the uWSGI
CMD ["uwsgi", "app.ini"]
In our backend folder, we should have these files now:
app.ini
app.py
Dockerfile
Pipfile
requirements.txt
wsgi.py
Chapter 3. Deployment (nginx)
- ### All we need to do is to re-direct request from outside to our uWSGI server in container. Luckily we can directly access to them using the image name.
for more details: http://nginx.org/en/docs/beginners_guide.html
The nginx listen to 80 port and direct calls to different locations such as "/diary" to different internal ports. (flask: 8080 in this case)
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass flask:8080;
}
}
- Then, the Dockerfile
FROM nginx
# remove the default conf
RUN rm /etc/nginx/conf.d/default.conf
# copy the nginx.conf in our filesystem into the image filesystem
COPY nginx.conf /etc/nginx/conf.d
Chapter 4: docker-compose to connect all containers
All the containers are in a virtual lan environment.
- go to the root folder of the project, now you should have following folders
backend/
frontend/
database/
nginx/
- Create a new file called
docker-compose.yml
# check your version: https://docs.docker.com/compose/compose-file/
version: "3.7"
services:
# first container
backend:
# look for dockerfile and build the container
build: ./backend
container_name: backend
restart: always
# set enviornemt variables
environment:
- APP_NAME=FlaskApp
# mount the volumes so we can change code and hot reload
volumes:
- './backend:/backend'
# expose port on the container, only to other containers
expose:
- 8080
nginx:
build: ./nginx
container_name: nginx
restart: always
# port allows the host machine to link to container
# pass 80 from host machine to 80 of the image filesystem
ports:
- "80:80"
NOTE: we added a volumes here that allows future hot-reload to happen. (together with the uWSGI's py-autoreload)
NOTE: The difference about ports and expose:
expose allow communication between multiple containers
ports map one of the container port to the host machine port (the real internet)
Top comments (2)
Thanks for the article. BTW Chapter 2 is missing :)
Wonderful article :) but chapter 2( vueJS probably) missing :(