Python Flask Web项目部署教程
欢迎您使用本教程
本教程介绍在Linux系统下通过Gunicorn部署Python Flask项目、Nginx代理静态资源、数据库MySQL、Fail2ban保护服务器的详细教程,使用系统以及软件版本如下:
- Linux系统:CentOS-Stream-9
- Python解释器:3.11.9
- Gunicorn:26.0.0
- Nginx:1.30.2
- MySQL:8.0
- Fail2ban:2.5
一、准备工作
- 在根目录创建www文件夹,在文件夹中分别创建data、static、你的项目名称文件夹,如图所示:

- data:存放安装包等文件
- static:存放Nginx管理的静态文件
- 你的项目名称:存放你的Flask项目代码文件(static静态文件除外)
- 在data目录中上传或下载以下文件:
- Python-3.11.9.tgz
- nginx-1.30.2.tar.gz
- mysql84-community-release-el9-1.noarch.rpm
- 在static中上传项目所需的静态文件,如没有则忽略
- 在你的项目名称文件夹中上传你的Flask项目代码文件(static静态文件除外)
二、安装python解释器
1.安装依赖
直接运行以下命令:
yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make运行结果如图所示;
2.解压
进入data目录解压 Python-3.11.9.tgz 文件:
cd data
tar -zxvf Python-3.11.9.tgz运行结果如图:
3.配置
进入 Python-3.11.9 目录:
cd Python-3.11.9可以看到有 configure 文件,如图; 
执行以下命令:
./configure --prefix=/opt/python311 --enable-optimizations4.编译&安装
执行以下命令:
make & make install运行结果如图: 
5.创建软连接
ln -s /opt/python311/bin/python3.11 /usr/local/bin/python3116.配置环境变量
执行
vi ~/.bash_profile在文件中加上以下内容:
export PYTHON_HOME=/opt/python311
export PATH=$PYTHON_HOME/bin:$PATH7.执行source ~/.bash_profile命令使配置生效。执行echo命令,查看是否配置成功
三、虚拟环境的创建及使用
1.创建虚拟环境
先进入项目文件夹,执行:
cd /
cd www/项目文件夹创建虚拟环境,执行:
python3.11 -m venv venv无报错即为成功,多出一个venv文件夹,如图:
2.进入虚拟环境
在项目文件夹执行:
source venv/bin/activate结果如图,显示venv即为成功: 
3.退出环境
执行,venv消失即为成功
deactivate如图: 
四、gunicorn配置及启动
1.配置文件
将以上内容添加到gunicorn.conf.py文件中,如没有这在项目文件夹新建一个
# 项目目录
chdir = '/www/qingyuweb'
# 指定进程数
workers = 4
# 指定每个进程开启的线程数
threads = 2
#启动用户
user = 'root'
# 后台运行
daemon = True # 后台运行
# 启动模式
worker_class = 'sync'
# 绑定的ip与端口
bind = '0.0.0.0:8000'
# 设置进程文件目录(用于停止服务和重启服务,请勿删除)
pidfile = '/www/qingyuweb/logs/gunicorn.pid'
# 设置访问日志和错误信息日志路径
accesslog = '/www/qingyuweb/logs/gunicorn_acess.log'
errorlog = '/www/qingyuweb/logs/gunicorn_error.log'
# 日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
# debug:调试级别,记录的信息最多;
# info:普通级别;
# warning:警告消息;
# error:错误消息;
# critical:严重错误消息;
loglevel = 'info'
# 自定义设置项请写到该处
# 最好以上面相同的格式 <注释 + 换行 + key = value> 进行书写,
# PS: gunicorn 的配置文件是python扩展形式,即".py"文件,需要注意遵从python语法,
# 如:loglevel的等级是字符串作为配置的,需要用引号包裹起来2.python第三方库依赖安装(包括gunicorn)
进入虚拟环境运行:
pip install -r requirements.txt需确保项目文件夹存在requirements.txt文件,如图: 
3.启动命令(app代表项目入口文件名称,如不同清修改)
python -m gunicorn app:app无报错即为成功,如图: 
五、nginx安装/配置/启动
1.解压文件
先进入data文件夹
cd data运行命令解压 nginx-1.30.2.tar.gz 文件
tar -zxvf nginx-1.30.2.tar.gz运行结果如图: 
2.配置
先进入 nginx-1.30.2 文件夹 可以看到有一个 configure 文件:
运行以下命令:
./configure --prefix=/opt/nginx4.编译&安装
执行以下命令:
make & make install5.启动 nginx
进入 nginx 安装目录,执行:
cd /opt/nginx/sbin/可以看到一个 nginx 文件,如图:
运行启动命令:
./nginx无报错即为成功
6.配置文件(实现反向代理和动静分离)
运行以下命令,进入 nginx 配置文件夹
cd /opt/nginx/conf在 nginx.conf 文件中的server部分加上一下内容:
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
}
location ~ .*\.(js|css|png|jpg|jpeg|gif|ico|svg|mp4|m3u8|ttf|woff)$
{
root /www/;
expires 30h;
}7.重新加载配置文件
./nginx -s reload8.其它命令(都需在 nginx 的sbin目录下运行,否则会报错)
停止
./nginx -s stop安全退出
./nginx -s quit六、mysql安装
1.查询已安装的 MariaDB 相关软件包
rpm -qa|grep mariadb如图即为没有,跳过步骤2:
2.删除MariaDB
rpm -e mariadb-libs-5.5.64-1.el7.x86_64 --nodeps3.安装网络安装工具wget
yum -y install wget如图即为成功:
4.安装配置文件
先进入data目录:
cd /
cd www/data运行:
yum -y install mysql84-community-release-el9-1.noarch.rpm结果如图所示: 
5.安装mysql
运行:
yum -y install mysql-community-server运行结果如图所示:
6.启动mysql
运行:
systemctl start mysqld检查 mysql 运行状态:
systemctl status mysqld正常如图所示:
7.查看临时密码
grep 'temporary password' /var/log/mysqld.log密码如图:
8.修改初始密码
先登录 mysql,运行并输入临时密码:
mysql -uroot -p如图:
运行下列代码修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY '密码';运行结果如图:
9.mysql配置文件
编辑/ets/my.conf文件,加上以下内容(性能好的服务器请忽略):
max_connections=10
wait_timeout=30
interactive_timeout=30
innodb_buffer_pool_size=128M
innodb_log_file_size=128M
innodb_log_buffer_size=4M
sort_buffer_size=32K
read_buffer_size=32K
read_rnd_buffer_size=32K
join_buffer_size=32K
tmp_table_size=16M
max_heap_table_size=16M
performance_schema=OFF
default-storage-engine=innodb
innodb_read_io_threads=1
innodb_write_io_threads=1
innodb_buffer_pool_instances=1七、fail2ban
1.安装依赖
sudo dnf install -y epel-release运行结果如图所示:
2.安装 fail2ban 以及防火墙依赖
yum install -y fail2ban fail2ban-firewalld运行结果如图所示:
3.启动
sudo systemctl start fail2ban无报错即为启动成功:
4.备份配置文件
执行:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local后续配置文件的修改一律在 jail.local 文件中,或在其他新建文件中,绝对禁止修改 jail.conf 中的内容
5.SSH防御 防止暴力破解
删除默认文件
rm -rf /etc/fail2ban/jail.d/*编辑ssh策略
vi /etc/fail2ban/jail.d/sshd.local在文件中添加以下内容:
[sshd]
enabled = true
mode = normal
backend = systemd重启服务
systemctl restart fail2ban查看封锁列表
fail2ban-client status查看SSH封锁情况
fail2ban-client status sshd6.创建网站拦截规则
编辑 nginx 网址策略
vi /etc/fail2ban/jail.d/nginx.local在文件中添加以下内容:
[nginx-http-auth]
enabled = true
mode = fallback
port = http,https
logpath = /opt/nginx/logs/access.log
[nginx-limit-req]
enabled = true
port = http,https
logpath = /opt/nginx/logs/access.log
[nginx-botsearch]
enabled = true
port = http,https
logpath = /opt/nginx/logs/access.log
[nginx-bad-request]
enabled = true
port = http,https
logpath = /opt/nginx/logs/access.log
[php-url-fopen]
enabled = true
port = http,https
logpath = /opt/nginx/logs/access.log查看nginx封锁情况
fail2ban-client status nginx-http-auth查看总日志
tail -f /var/log/fail2ban.log八、其它命令
检查防火墙状态
systemctl status firewalld启动/停止防火墙
systemctl start firewalld
systemctl stop firewalld开启/停止端口
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --zone=public --remove-port=8080/tcp --permanent重载防火墙
firewall-cmd --reload查看已开发端口
firewall-cmd --list-ports查看端口占用
sudo ss -tulnp | grep :8000创建用户
useradd zhangsan
passwd zhangsan创建用户,不可登录
useradd -M -s /sbin/nologin www参数解释
- -M 不创建家目录
- -s /sbin/nologin 禁止登录服务器
授与权限
chown -R www:www /www/qingyuweb资源监控脚本
编辑脚本
vi /usr/local/bin/server_monitor.sh在文件中添加以下内容:
#!/bin/bash
# 所有记录写入同一个日志文件
LOG_FILE="/var/log/server_monitor.log"
# 分隔线
divider() {
echo "========================================================================" >> "${LOG_FILE}"
}
# 主监控逻辑
monitor() {
local NOW_TIME="$(date '+%Y-%m-%d %H:%M:%S')"
divider
echo "监控时间: ${NOW_TIME}" >> "${LOG_FILE}"
echo "========== 服务器资源监控 ==========" >> "${LOG_FILE}"
# 1. 系统负载 & CPU
echo -e "\n【系统负载 & CPU】" >> "${LOG_FILE}"
echo "1/5/15分钟负载: $(uptime | awk -F'load average:' '{print $2}')" >> "${LOG_FILE}"
top -bn1 | grep '^%Cpu' | awk '{printf "CPU 使用: 用户 %.1f%%, 系统 %.1f%%, 空闲 %.1f%%\n", $2, $4, $8}' >> "${LOG_FILE}"
# 2. 内存
echo -e "\n【内存使用】" >> "${LOG_FILE}"
free -h | awk 'NR==2{print "内存: 总"$2", 已用"$3", 空闲"$4", 缓存"$6}' >> "${LOG_FILE}"
# 3. 磁盘
echo -e "\n【磁盘使用】" >> "${LOG_FILE}"
df -h | grep -E '^/dev/' | grep -v 'tmpfs' | awk '{print $1 " 总"$2 ", 已用"$3 ", 剩余"$4 ", 使用率"$5}' >> "${LOG_FILE}"
# 4. 网络
echo -e "\n【网络状态】" >> "${LOG_FILE}"
echo "TCP 总连接: $(ss -t | wc -l)" >> "${LOG_FILE}"
echo "已建立连接: $(ss -t state established | wc -l)" >> "${LOG_FILE}"
echo "等待连接: $(ss -t state time-wait | wc -l)" >> "${LOG_FILE}"
# 5. fail2ban
echo -e "\n【Fail2Ban 状态】" >> "${LOG_FILE}"
if pgrep -f fail2ban > /dev/null; then
echo "运行状态: 正在运行" >> "${LOG_FILE}"
echo "累计封禁IP数: $(fail2ban-client status 2>/dev/null | grep 'Total banned' | awk '{print $4}')" >> "${LOG_FILE}"
echo "SSH封禁列表: $(fail2ban-client status sshd 2>/dev/null | grep 'Banned IP list' | cut -d: -f2 | xargs)" >> "${LOG_FILE}"
else
echo "运行状态: 未运行" >> "${LOG_FILE}"
fi
# ==================== Nginx 状态(万能检测,不依赖路径)====================
echo -e "\n【Nginx 状态】" >> "${LOG_FILE}"
if pgrep -f nginx > /dev/null; then
PID=$(pgrep -f nginx | head -1)
NUM=$(pgrep -f nginx | wc -l)
CPU=$(ps -p $PID -o pcpu= | xargs)
MEM=$(ps -p $PID -o pmem= | xargs)
echo "运行状态: 正在运行" >> "${LOG_FILE}"
echo "主进程PID: $PID" >> "${LOG_FILE}"
echo "进程数量: $NUM" >> "${LOG_FILE}"
echo "占用资源: CPU $CPU% 内存 $MEM%" >> "${LOG_FILE}"
else
echo "运行状态: 未运行" >> "${LOG_FILE}"
fi
# ==================== MySQL 状态(万能检测,不依赖路径)====================
echo -e "\n【MySQL 状态】" >> "${LOG_FILE}"
if pgrep -f mysqld > /dev/null || pgrep -f mysql > /dev/null; then
PID=$(pgrep -f mysqld 2>/dev/null || pgrep -f mysql 2>/dev/null | head -1)
NUM=$(pgrep -f mysqld 2>/dev/null || pgrep -f mysql 2>/dev/null | wc -l)
CPU=$(ps -p $PID -o pcpu= | xargs)
MEM=$(ps -p $PID -o pmem= | xargs)
echo "运行状态: 正在运行" >> "${LOG_FILE}"
echo "主进程PID: $PID" >> "${LOG_FILE}"
echo "进程数量: $NUM" >> "${LOG_FILE}"
echo "占用资源: CPU $CPU% 内存 $MEM%" >> "${LOG_FILE}"
else
echo "运行状态: 未运行" >> "${LOG_FILE}"
fi
# ==================== Gunicorn 状态(万能检测,不依赖路径)====================
echo -e "\n【Gunicorn 状态】" >> "${LOG_FILE}"
if pgrep -f gunicorn > /dev/null; then
PID=$(pgrep -f gunicorn | head -1)
NUM=$(pgrep -f gunicorn | wc -l)
CPU=$(ps -p $PID -o pcpu= | xargs)
MEM=$(ps -p $PID -o pmem= | xargs)
echo "运行状态: 正在运行" >> "${LOG_FILE}"
echo "主进程PID: $PID" >> "${LOG_FILE}"
echo "进程数量: $NUM" >> "${LOG_FILE}"
echo "占用资源: CPU $CPU% 内存 $MEM%" >> "${LOG_FILE}"
else
echo "运行状态: 未运行" >> "${LOG_FILE}"
fi
echo -e "\n" >> "${LOG_FILE}"
divider
}
# 执行监控
monitor授予执行权限
chmod +x /usr/local/bin/server_monitor.sh设置定时执行
crontab -e
*/5 * * * * /usr/local/bin/server_monitor.sh内存查看/释放
free -h
sync && echo 3 > /proc/sys/vm/drop_caches