Docker + Flask + Vue + Nginx - deployment and development in one package (1)

herbzhao

Herbz

Posted on April 10, 2020

Docker + Flask + Vue + Nginx - deployment and development in one package (1)

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)

💖 💪 🙅 🚩
herbzhao
Herbz

Posted on April 10, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related