一个简单的 Flask 应用
需要访问 mariadb
数据库, 简单的设计一个 user
表来存放用户信息
$ tree -L 2
.
├── app.py
├── com
│ ├── __init__.py
│ ├── config.py
│ └── models.py
├── requirements.txt
├── templates
│ └── index.html
└── views
├── __init__.py
└── main.py
app.py
from flask import Flask
from views import main_bp
from com.models import db, UserModel
from flask_migrate import Migrate, init, migrate, upgrade
import click
import shutil
app = Flask(__name__)
app.config.from_object("com.config")
app.register_blueprint(main_bp)
db.init_app(app)
Migrate(app=app, db=db)
@app.cli.command("init-db")
def init_db():
"""Init database"""
init()
migrate()
upgrade()
shutil.rmtree('./migrations')
print('Database initilized.')
@app.cli.command("create-user")
@click.argument("name")
def create_user(name):
"""Create user CLI"""
user = UserModel()
user.username = name
db.session.add(user)
db.session.commit()
print(f"User: {name} added.")
com/config.py
import os
# Flask config
DEBUG = False
JSON_AS_ASCII = False
SECRET_KEY = 'somerandomcharacter'
# Database config read from environment variables
DB_HOST = os.getenv('DB_HOST')
DB_PORT = os.getenv('DB_PORT')
DB_NAME = os.getenv('DB_NAME')
DB_USERNAME = os.getenv('DB_USERNAME')
DB_PASSWORD = os.getenv('DB_PASSWORD')
SQLALCHEMY_DATABASE_URI = f'mysql+pymysql://{DB_USERNAME}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8'
SQLALCHEMY_TRACK_MODIFICATIONS = False
com/models.py
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column, Integer, Text
db = SQLAlchemy()
class UserModel(db.Model):
__tablename__ = 'user'
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(Text)
views/main.py
from flask import Blueprint, render_template
from com.models import UserModel
bp = Blueprint('main', __name__, url_prefix='/')
@bp.route('/')
def index():
data = UserModel.query.all()
return render_template('index.html', data=data)
views/__init__.py
from .main import bp as main_bp
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Flask</title>
</head>
<body>
<h1>Welcome to My Flask</h1>
<h2>User list:</h2>
<ul>
{%for d in data%}
<li>{{d.username}}</li>
{%endfor%}
</ul>
</body>
</html>
requirements.txt
flask
flask-sqlalchemy
flask-migrate
pymysql
构建 Docker Image
- 编辑
Dockerfile
FROM python:3.10.6-alpine
EXPOSE 80
WORKDIR /app
RUN apk update
COPY requirements.txt /app
RUN pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
RUN pip3 install -r requirements.txt --no-cache-dir
COPY . .
CMD ["python3", "-m", "flask", "run", "--host=0.0.0.0", "--port=80"]
- 构建 Image
docker build -t my-flask:latest .
- 测试运行
docker run -it -p 8000:80 --rm my-flask
- 以 Daemon 方式后台运行
docker run -d -p 8000:80 my-flask
- 调用
flask
CLI 自定义命令初始化数据库和添加用户
docker exec [CONTAINER_ID] flask init-db
docker exec [CONTAINER_ID] flask create-user dexterlien
多 Container 联动部署
应用中用到了 MariaDB, 我们可以将数据库也以容器的方式一同进行部署, 需要用到 docker-compose
- 安装
docker-compose
# Ubuntu 可以直接使用 apt 安装
sudo apt install -y docker-compose
# 也可以手动下载安装
sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose
- 编辑
docker-compose.yml
version: '3'
services:
flask-app:
container_name: my-flask
build: .
environment:
- DB_HOST=mariadb
- DB_PORT=3306
- DB_NAME=flask_db
- DB_USERNAME=root
- DB_PASSWORD=mypwd
restart: always
ports:
- '8000:80'
depends_on:
- mariadb
links:
- mariadb
networks:
- backend
mariadb:
container_name: mariadb
image: mariadb:latest
restart: always
environment:
MYSQL_ROOT_PASSWORD: mypwd
MYSQL_DATABASE: flask_db
expose:
- '3306'
volumes:
- ./database:/var/lib/mysql
networks:
- backend
networks:
backend:
volumes:
app:
database:
- 部署和启动
docker-compose up