DEV Community

Herbz
Herbz

Posted on • Updated on

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)

Top comments (2)

Collapse
 
averkij profile image
Sergei Averkiev

Thanks for the article. BTW Chapter 2 is missing :)

Collapse
 
sreeparvathik profile image
Sreeparvathi K

Wonderful article :) but chapter 2( vueJS probably) missing :(