Flask+Vue+Nginx+MySQL Dockerize on Linux - [Setting Up]

geunyeongii·2022년 1월 29일
0

사용자가 새로운 글을 추가하고 다른 사람들이 추가한 글들을 볼 수 있는 게시판을 만들예정이다. 게시글을 저장할 MySQL 데이터베이스, Flask를 사용하는 백엔드 API 및 Flask Restful, VueJS를 사용하는 프론트 엔드 인스턴스를 만들어 Docker와 연결시켜볼 것이다.

VirtualBox Setting

How to install
Ubuntu 20.04.3 LTS

Ubuntu Setting

db, api, nginx 폴더를 만든다.

Creating the database

MySQL install
workspace/db/init.sql을 다음과 같이 작성하여 데이터베이스를 생성하고 테이블을 만들어 INSERT시켜준다.

CREATE DATABASE `quotes_db`;
USE `quotes_db`;

CREATE TABLE `quote` (
    `id` INT(11) PRIMARY KEY AUTO_INCREMENT,
    `quote` VARCHAR(512) NOT NULL,
    `quote_by` VARCHAR(100),
    `added_by` VARCHAR(100),
    `created` DATETIME DEFAULT CURRENT_TIMESTAMP(),
    `updated` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP()
);

INSERT INTO `quote` (`quote`, `quote_by`, `added_by`)
VALUES ('Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.', 'Allan Kay', 'Sam');

gnyii계정의 databases는 만들어져있지 않으므로 위의 코드를 실행하여 생성한다.

이와같은 오류가 발생하였다. 해결방법은 루트 계정으로 접속해서 gnyii계정에 권한을 주어야 했다.
이제 다시 init.sql 파일을 적용시켜보겠다. 이제는 잘 실행되는 것을 확인 할 수 있었다.

Creating the API

python3 install
▶ Python-venv install -> sudo apt-get install python3-venv

게시판을 읽고 쓸 수 있는 아주 간단한 API를 만들 것이며, 이 앱은 하나의 endpoint를 가질 것이다.

우선 api폴더로 cd한다음 아래의 코드로 가상 환경 셋팅을 해준다.

python -m venv env
source env/bin/activate

이후 아래의 의존성들을 설치해준다.
pip install flask flask-restful aqalchemy pymysql flask-cors uwsgi

Flask는 Restful API를 만들 때 사용되고, SQLAlchemy나 PyMySQL은 db를 사용할 때 사용된다. 마지막으로 Uswgi는 Nginx를 서비스하기 위해 필요한 것이다.

의존성을 저장하기 위한 파일을 만들기 위해 pip freeze > requirements.txt를 실행하여 txt파일을 생성한다.

이제 api폴더 내에서 db.py, views.py, run.py를 생성한다.

# db.py
from datetime import date, datetime
from decimal import Decimal

from sqlalchemy import create_engine


class Db():
    def __init__(self):
        db_url = "mysql+pymysql://gnyii:wnrmsdud12!@localhost/quotes_db"

        engine = create_engine(db_url)
        self.connection = engine.connect()

    def __del__(self):
        self.connection.close()

    def clean_select_row(self, row, keys):
        try:
            clean_row = [str(field) if isinstance(field, datetime) or isinstance(
                field, Decimal) or isinstance(field, date) else field for field in list(row)]
            current_row = {}
            for i in range(len(keys)):
                current_row[keys[i]] = clean_row[i]
            return current_row
        except:
            return None

    def clean_select_results(self, data, keys):
        if len(data) == 0:
            return {}
        result_data = []
        for row in data:
            result_data.append(self.clean_select_row(row, keys))
        return result_data

db_url 형식 > mysql+pymysql://username:password@host/db_name

# views.py
from db import Db
from flask import request
from flask_restful import Resource
from sqlalchemy import text as sql_text


class Quote(Resource):
    """ The quotes View """

    def __init__(self):
        self.db = Db()

    def get(self):
        """ Returns a list of quotes """
        query = "SELECT * FROM quote ORDER BY created DESC"
        res = self.db.connection.execute(query)
        rows = res.fetchall()
        keys = res.keys()
        quotes = self.db.clean_select_results(rows, keys)

        return {
            'quotes': quotes
        }

    def post(self):
        """
        Add a quote to the db 
        Expect a JSON payload with the following format
        {
            "quote": "The quote",
            "quote_by": "The person who said the quote",
            "added_by": The person who is posting the quote"
        }
        """
        data = request.get_json()
        query = "INSERT INTO `quote` (`quote`, `quote_by`, `added_by`) VALUES (:quote, :quote_by, :added_by)"
        try:
            self.db.connection.execute(sql_text(query), data)
            return True
        except:
            return False
# run.py
from flask import Flask
from flask_cors import CORS
from flask_restful import Api
from views import Quote

app = Flask(__name__)
CORS(app)
api = Api(app)


api.add_resource(Quote, '/')

if __name__ == "__main__":
    app.run(port=5000, debug=True)

이제 api를 실행시키고 테스트를 해봤다. 글을 저장하고, POST request를 보내봤다.

API가 정상 작동하는 것을 볼 수있다. 이제는 Vue로 간단하게 게시글을 읽을 수 있다.

profile
✏️세상의 모든 기록 ✏️

0개의 댓글