一、项目概述
本项目是一个基于 Flask 的校园众筹平台,采用 Docker 容器化部署,Nginx 作为反向代理服务器。本文档提供一套完整的手动部署步骤及其自动化脚本,帮助你在 CentOS 7+ 服务器上快速搭建环境,并确保基本的安全性。
注意:当前网站仅用于技术演示,未投入实际生产,因此安全性措施以满足基本防护为主(如仅开放必要端口、最小权限原则)。若用于生产环境,请根据业务需求加强数据备份、访问控制等。
二、环境准备
2.1 服务器要求
-
操作系统:CentOS 7 / RHEL 7+(或其他 systemd 发行版)
-
已安装 Docker 和 Docker Compose 插件
-
已安装 Nginx
-
防火墙使用 firewalld(脚本自动配置)
-
云服务器需在安全组开放 80 端口(TCP)
2.2 项目文件
确保服务器上存在以下文件(路径可自定义):
-
/opt/campus_project/campus_crowdfunding/-
app.py--- Flask 应用主文件,确保监听0.0.0.0:8000且debug=False -
requirements.txt--- Python 依赖列表 -
Dockerfile--- 用于构建 Flask 镜像 -
docker-compose.yml--- 定义服务(web 容器、数据库等)
-
-
/etc/nginx/nginx.conf--- Nginx 主配置文件(需提前准备好反向代理配置)
若尚未编写
docker-compose.yml和Dockerfile,请先根据项目需求创建。
三、手动部署步骤(简述)
-
清理旧环境
bash
docker compose down docker stop $(docker ps -a | grep campus | awk '{print $1}') 2>/dev/null docker rm $(docker ps -a | grep campus | awk '{print $1}') 2>/dev/null docker rmi $(docker images | grep campus | awk '{print $3}') 2>/dev/null -
更新代码与权限
bash
rm -rf /opt/campus_project/campus_crowdfunding/* # 谨慎使用,确保已备份 chmod -R 755 /opt/campus_project/campus_crowdfunding chown -R root:root /opt/campus_project/campus_crowdfunding -
检查基础服务
bash
systemctl status docker systemctl status nginx -
修改 Flask 配置
确保
app.py中包含:app.run(host='0.0.0.0', port=8000, debug=False) -
构建并启动容器
bash
cd /opt/campus_project/campus_crowdfunding docker compose up -d --build docker compose ps docker compose logs campus_app curl http://127.0.0.1:8000 # 验证本地访问 -
配置 Nginx
bash
vi /etc/nginx/nginx.conf # 添加或修改反向代理配置 nginx -t # 检查语法 systemctl restart nginx netstat -tulpn | grep :80 # 确认80端口监听 -
防火墙与安全组
bash
firewall-cmd --add-port=80/tcp --permanent firewall-cmd --reload最后登录云控制台,确保安全组入方向放行 80 端口(来源 0.0.0.0/0)。
四、自动化部署脚本
将上述手动步骤封装为脚本,减少人工干预,提高部署效率。脚本已集成错误处理、等待机制和友好提示。
4.1 脚本内容
创建文件 /opt/campus_project/campus_crowdfunding/deploy.sh,并赋予执行权限:
bash
chmod +x /opt/campus_project/campus_crowdfunding/deploy.sh
脚本完整内容如下(可根据实际路径修改变量):
bash
#!/bin/bash
set -euo pipefail
# ==================================================
# 校园众筹项目自动部署脚本
# 适用环境:CentOS/RHEL 7+,使用 systemd、firewalld
# 使用方法:sudo ./deploy.sh
# 注意:请确保在运行前已手动修改 app.py 和 nginx.conf(如需)
# ==================================================
# ---------- 配置变量(请根据实际情况修改)----------
PROJECT_DIR="/opt/campus_project/campus_crowdfunding"
FLASK_PORT=8000
NGINX_PORT=80
COMPOSE_FILE="docker-compose.yml"
BACKUP_NGINX_CONF=true
AUTO_CLEAN_FILES=false
# -------------------------------------------------
# 颜色定义
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; BLUE='\033[0;34m'; NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"; }
log_step() { echo -e "${BLUE}>>>${NC} $1"; }
# 检查必要命令
check_commands() {
local cmds=("docker" "nginx" "firewall-cmd" "systemctl" "curl")
for cmd in "${cmds[@]}"; do
if ! command -v "$cmd" &> /dev/null; then
log_error "命令 '$cmd' 未找到,请安装后重试。"
exit 1
fi
done
if ! docker compose version &> /dev/null; then
log_error "docker compose 插件不可用,请安装或使用旧版 docker-compose。"
exit 1
fi
}
# 等待 Flask 应用就绪
wait_for_flask() {
local url="http://127.0.0.1:$FLASK_PORT"
log_info "等待 Flask 应用启动(最多 60 秒)..."
for i in {1..30}; do
if curl -s -f "$url" > /dev/null 2>&1; then
log_info "Flask 应用已就绪"
return 0
fi
sleep 2
done
log_error "Flask 应用启动超时,请检查容器日志。"
return 1
}
# 主流程
main() {
log_step "开始部署校园众筹项目"
check_commands
# 进入项目目录
if [ ! -d "$PROJECT_DIR" ]; then
log_error "项目目录 $PROJECT_DIR 不存在"
exit 1
fi
cd "$PROJECT_DIR"
log_info "切换到目录:$PROJECT_DIR"
# 清理旧容器和镜像
log_step "步骤1:清理旧容器及镜像"
if [ -f "$COMPOSE_FILE" ]; then
log_info "执行 docker compose down --rmi all --volumes"
docker compose down --rmi all --volumes 2>/dev/null || log_warn "清理过程中出现非致命错误,继续执行"
else
log_warn "未找到 $COMPOSE_FILE,跳过 compose 清理"
fi
# 清理旧文件(可选)
if [ "$AUTO_CLEAN_FILES" = true ]; then
log_step "步骤2:清理项目目录下的所有文件"
read -p "是否确定删除 $PROJECT_DIR 下的所有文件?(y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rm -rf "${PROJECT_DIR:?}"/*
log_info "已清空 $PROJECT_DIR"
else
log_warn "跳过文件清理"
fi
else
log_info "跳过自动文件清理(AUTO_CLEAN_FILES=false),请手动确保文件已更新"
fi
# 设置目录权限
log_step "步骤2:设置目录权限"
chmod -R 755 "$PROJECT_DIR"
chown -R root:root "$PROJECT_DIR"
log_info "权限设置为 755,所有者 root:root"
# 检查 Docker 和 Nginx 服务
log_step "步骤3:检查基础服务状态"
systemctl is-active --quiet docker || { log_error "Docker 未运行"; exit 1; }
log_info "Docker 运行正常"
systemctl is-active --quiet nginx || { log_error "Nginx 未运行"; exit 1; }
log_info "Nginx 运行正常"
# 检查 Nginx 当前语法
log_info "检查现有 Nginx 配置语法"
nginx -t || { log_error "Nginx 配置语法错误,请先手动修复"; exit 1; }
# 构建并启动容器
log_step "步骤5:构建并启动 Flask 容器"
log_info "执行 docker compose up -d --build"
docker compose up -d --build
log_info "检查容器状态"
docker compose ps
log_info "容器最新日志:"
docker compose logs --tail=20 campus_app || true
wait_for_flask || { log_error "Flask 应用未正常响应,退出部署"; exit 1; }
# Nginx 配置处理
log_step "步骤6:Nginx 配置检查与重载"
if [ "$BACKUP_NGINX_CONF" = true ] && [ -f /etc/nginx/nginx.conf ]; then
backup_file="/etc/nginx/nginx.conf.bak.$(date +%Y%m%d-%H%M%S)"
cp /etc/nginx/nginx.conf "$backup_file"
log_info "已备份当前 Nginx 配置至 $backup_file"
fi
log_warn "请手动检查/编辑 Nginx 配置文件:vi /etc/nginx/nginx.conf"
read -p "确认已完成 Nginx 配置修改?(y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_error "用户取消部署"
exit 1
fi
log_info "检查 Nginx 配置语法"
nginx -t || { log_error "Nginx 配置语法错误,请检查刚才的修改"; exit 1; }
log_info "重载 Nginx 服务"
systemctl reload nginx
# 验证端口监听
log_info "验证端口 $NGINX_PORT 监听状态"
if netstat -tulpn 2>/dev/null | grep -q ":$NGINX_PORT "; then
log_info "端口 $NGINX_PORT 已被监听"
else
log_warn "端口 $NGINX_PORT 未被监听,请检查 Nginx 配置"
fi
# 防火墙放行
log_info "检查防火墙端口 $NGINX_PORT"
if firewall-cmd --list-ports | grep -q "$NGINX_PORT/tcp"; then
log_info "防火墙端口 $NGINX_PORT 已开放"
else
log_warn "防火墙端口 $NGINX_PORT 未开放,尝试添加"
firewall-cmd --add-port="$NGINX_PORT/tcp" --permanent
firewall-cmd --reload
log_info "防火墙端口已添加"
fi
# 最终提示
log_step "部署完成"
echo -e "${GREEN}================================================"
echo "请务必登录云控制台,确认安全组已放行 $NGINX_PORT 端口(0.0.0.0/0)"
echo "测试访问:http://你的服务器公网IP"
echo "查看容器日志:docker compose logs -f campus_app"
echo "================================================${NC}"
}
main "$@"
4.2 使用前准备
-
修改变量 :根据实际项目路径修改
PROJECT_DIR、FLASK_PORT等。 -
确保配置正确:
-
app.py已按生产环境配置(debug=False)。 -
Nginx 配置文件已准备好反向代理规则(示例见下文)。
-
docker-compose.yml中服务名称为campus_app(脚本中日志查看用了该名称,若不同请修改)。
-
-
数据持久化 :若数据库使用容器,确保
docker-compose.yml中已挂载卷,否则down --volumes会删除数据。
4.3 执行脚本
bash
sudo /opt/campus_project/campus_crowdfunding/deploy.sh
脚本运行过程中会:
-
自动清理旧容器、镜像和网络。
-
询问是否删除项目目录文件(默认否,需手动更新代码)。
-
设置目录权限。
-
检查 Docker 和 Nginx 服务。
-
构建并启动容器,等待 Flask 就绪。
-
暂停等待用户编辑 Nginx 配置(按 y 继续)。
-
验证 Nginx 语法并重载。
-
开放防火墙端口。
-
提示检查云安全组。
五、Nginx 配置示例
在 /etc/nginx/nginx.conf 的 http 块内添加或修改以下 server 块(注意不要覆盖原有配置):
nginx
server {
listen 80;
listen [::]:80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
如果已有其他服务(如 8082 端口的默认页面),请保留并确保不冲突。