docker 部署 flask 项目

docker 部署 flask 项目

项目结构说明

nginx 做反向代理,gunicorn 启动 flask,flask 连接 mysql

镜像

  • nginx:1.21.3
  • mysql:8
  • flask_app(以 python 镜像为基础构建的项目镜像)

docker 版本:

  • Docker version 20.10.9
  • Docker Compose version v2.0.1

镜像说明

nginx

  1. 处理前端页面及静态文件请求;

  2. 代理 flask 的后端服务;

  3. nginx 配置

    #user nobody;
    worker_processes 4;
    #error_log logs/error.log;
    #error_log logs/error.log notice;
    #error_log logs/error.log info;
    #pid logs/nginx.pid;
    events {
    worker_connections 1024;
    }
    http {
    include mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr [$request_time $upstream_response_time] [$time_local -$msec] [$request] [$request_body] '
    '$status $body_bytes_sent '
    '"$http_user_agent"'
    '$scheme $server_addr $request_uri';
    #access_log logs/access.log main;
    sendfile on;
    #tcp_nopush on;
    #keepalive_timeout 0;
    keepalive_timeout 600;
    #gzip on;
    upstream flask_app {
    server 172.16.238.10:5000;
    }
    server {
    listen 8080;
    server_name localhost;
    server_tokens off;
    # 前端页面
    location /index.html {
    root /usr/share/nginx/html/web;
    index index.html index.htm;
    }
    location /logo.png {
    root /usr/share/nginx/html/web;
    index index.html index.htm;
    }
    location /css {
    root /usr/share/nginx/html/web;
    index index.html index.htm;
    }
    location /js {
    root /usr/share/nginx/html/web;
    index index.html index.htm;
    }
    location /img {
    root /usr/share/nginx/html/web;
    index index.html index.htm;
    }
    location /fonts {
    root /usr/share/nginx/html/web;
    index index.html index.htm;
    }
    # 后端接口
    proxy_connect_timeout 600;
    proxy_read_timeout 600;
    proxy_send_timeout 600;
    location / {
    proxy_pass http://flask_app;
    proxy_redirect off;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 1024m;
    }
    }
    }

mysql

  1. 将数据库结构和初始数据导出为 sql 脚本,启动 mysql 容器时指定执行 mysql 初始化脚本

  2. mysql 初始化脚本

    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    CREATE flask_app;
    USE flask_app;
    -- ----------------------------
    -- Table structure for student
    -- ----------------------------
    DROP TABLE IF EXISTS `student`;
    CREATE TABLE `student` (
    `id` int(0) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
    `phone_num` varchar(13) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
    PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
    -- ----------------------------
    -- Records of student
    -- ----------------------------
    INSERT INTO `student` VALUES (1, 'tom', '13549872211');
    INSERT INTO `student` VALUES (2, 'Jerry', '13549872212');
    SET FOREIGN_KEY_CHECKS = 1;
  3. mysql 配置

    [mysqld]
    user=mysql
    character-set-server=utf8
    default_authentication_plugin=mysql_native_password
    lower_case_table_names=1
    secure_file_priv=/var/lib/mysql
    table_definition_cache=400
    [client]
    default-character-set=utf8
    [mysql]
    default-character-set=utf8

flask_app

镜像构建方式

构建 flask app 的镜像一般有两种方式:

  1. 直接以 python 镜像为基础,创建容器,再在容器中部署完成,最后导出为镜像;
  2. 使用Dockerfile构建镜像;

第一种比较麻烦,并且每次更新代码都需要重新手动构建镜像,因此使用Dockerfile方式

gunicorn 配置

import multiprocessing
# 监听的端口
bind = "0.0.0.0:5000"
# 防止在服务器上 work 启动过多,限制 work 数量
workers = multiprocessing.cpu_count() * 2 + 1 if multiprocessing.cpu_count() * 2 + 1 <= 6 else 6
backlog = 20480
debug = False
timeout = 500
errorlog = './log/gunicorn_error.log'

启动脚本

start.sh在容器启动时运行,使用gunicorn启动 flask_app

  1. 由于在Dockerfile中配置了WORKDIR,因此start.sh的执行环境默认就在WORKDIR
  2. 需要注意start.sh的换行符,需要设置为LF
#!/bin/bash
mkdir log
gunicorn -c gun.conf app:app --daemon
# 保留一个 bash
/bin/bash

Dockerfile 配置

# python 基础镜像版本
FROM python:3.8.12-slim
# 将代码复制到镜像中的目录下
COPY ./ /usr/local/flask_app/
# 设置工作目录,容器运行时,命令行默认就在这个目录
WORKDIR /usr/local/flask_app/
# apt-get 更换国内源
RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && \
sed -i 's|security.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g' /etc/apt/sources.list && \
apt-get update
# 安装环境
RUN chmod +x start.sh \
&& apt-get install -y -q -o Acquire::http::Pipeline-Depth=0 gcc \
&& apt-get clean \
&& pip3 install -r requirements.txt -i https://pypi.douban.com/simple
# 启动容器时,执行脚本
ENTRYPOINT ["./start.sh"]

构建镜像

  1. 执行构建命令时,将项目文件放入flask_app目录下,目录结构如下:
    --- flask_app
    --- Dockerfile
    --- start.sh
    --- app.py
    --- gun.py
    --- requirements.txt
    --- ... 其他项目文件
  2. flask_app目录下执行docker build -t flask_app .命令创建镜像

使用 docker-compose

单独去启动容器比较麻烦,使用 docker-compose 来管理容器更加方便,需要创建docker-compose.yml文件

docker-compose 配置文件

version: '3.3'
services:
mysql:
image: mysql:8
container_name: mysql_container
restart: always
command: bash -c "chmod 644 /etc/mysql/my.cnf && /entrypoint.sh mysqld --default-authentication-plugin=mysql_native_password"
volumes:
# 挂载 my.cnf 配置文件
- ./docker_volumes/mysql/my.cnf:/etc/mysql/my.cnf
# 初始化数据库,创建容器时会执行 init 下的 sql 语句
- ./docker_volumes/mysql/init:/docker-entrypoint-initdb.d/
environment:
# 设置密码
- 'MYSQL_ROOT_PASSWORD=1234'
# 设置时区
- 'TZ=Asia/Shanghai'
ports:
# 映射端口,如果不用外部访问可以不配置
- 3306:3306
logging:
driver: 'json-file'
options:
max-size: '100m'
networks:
flask_app_net:
ipv4_address: 172.16.238.3
nginx:
image: nginx:1.21.3
container_name: nginx_container
restart: always
volumes:
- ./docker_volumes/nginx/cert:/etc/nginx/cert
- ./docker_volumes/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
ports:
- '8080:8080'
environment:
- 'TZ=Asia/Shanghai'
logging:
driver: 'json-file'
options:
max-size: '100m'
networks:
flask_app_net:
ipv4_address: 172.16.238.7
flask_app:
image: flask_app
container_name: flask_app
restart: always
tty: true
environment:
- 'TZ=Asia/Shanghai'
volumes:
# 挂载目录
logging:
driver: 'json-file'
options:
max-size: '100m'
depends_on:
- mysql
networks:
flask_app_net:
ipv4_address: 172.16.238.10
# 创建一个虚拟网络,固定每个容器的 ip
networks:
flask-app-net:
name: flask_app_net
ipam:
driver: default
config:
- subnet: '172.16.238.0/24'

启动

目录结构

  1. 目录结构
    --- docker_demo
    --- docker-compose.yml
    --- docker_volumes
    --- mysql
    --- init
    --- init.sql # 数据库初始化
    --- my.cnf # mysql 配置
    --- nginx
    --- cert # nginx 证书
    --- conf
    --- nginx.conf # nginx 配置文件
  2. docker-compose.yml同级目录下执行docker-compose up -d

项目源码

posted @   守望人间  阅读(1944)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示