首页
/ Flask 应用部署实战:构建 wheel 包、配置生产密钥与启动 WSGI 服务器

Flask 应用部署实战:构建 wheel 包、配置生产密钥与启动 WSGI 服务器

2026-09-04 18:58:41作者:邬祺芯Juliet

本篇基于 Flask 官方教程的“Deploy to Production”章节展开,系统讲解如何把一个完整的 Flask 应用(以教程中的博客应用 Flaskr 为例)从开发机交付到生产服务器:构建可分发的 wheel 包并在目标机安装、重新初始化数据库、将默认的 SECRET_KEY 替换为随机密钥,最后用 Waitress 等生产级 WSGI 服务器替代内置开发服务器。读完本篇,你将掌握一条完整可复现的部署流水线,并理解 Flask instance 目录自动定位、实例配置加载等机制的源码级原理。

部署前提与整体流程

教程明确说明,这一部分假设你已经有一台可用于部署的服务器。它只给出如何创建分发包、安装并运行应用的整体概览,而不指定具体使用哪台服务器或哪套软件栈——你可以在开发电脑上搭建一个临时环境来演练这些步骤,但不建议用它托管真正对外公开的应用。关于各种具体的托管方式(Gunicorn、uWSGI、Apache、nginx 等),文档指向了专门的部署文档索引 docs/deploying/index.rst

整体流程可以概括为四步:

  1. 在开发机上把应用构建成 wheel(.whl)分发包;
  2. 把 wheel 拷贝到目标机器,创建新的虚拟环境并用 pip 安装;
  3. 重新执行 init-db 创建数据库(因为是新机器),并理解此时 instance 目录位置发生了变化;
  4. 在 instance 目录中写入随机生成的 SECRET_KEY,然后用生产 WSGI 服务器(如 Waitress)启动应用。

构建 wheel 包并在目标机安装

当你要把应用部署到别处时,需要构建一个 wheel.whl)文件。教程推荐安装并使用 build 工具来完成:

$ pip install build
$ python -m build --wheel

构建产物位于 dist/flaskr-1.0.0-py3-none-any.whl。文件名遵循 PEP 491 的格式:{项目名}-{版本}-{Python 标签}-{ABI 标签}-{平台标签}。以 Flaskr 为例:

  • 项目名为 flaskr、版本为 1.0.0,这两者直接来自 examples/tutorial/pyproject.toml 中的 [project] 段(name = "flaskr"version = "1.0.0"),构建后端为 flit_core.buildapi
  • py3 表示 Python 3 兼容的纯 Python 包,none 表示无特定 C ABI 依赖,any 表示与平台无关——这也解释了为什么这个 wheel 可以在任何平台的 Python 3 环境直接安装。

随后把该文件拷贝到另一台机器,按照 安装教程 创建一个新的虚拟环境(virtualenv),然后用 pip 安装:

$ pip install flaskr-1.0.0-py3-none-any.whl

pip 会连同项目的声明依赖一并安装——Flaskr 的 dependencies 只有一项 flask(见 examples/tutorial/pyproject.toml),因此 Flask 及其传递依赖会被自动拉取。

重新初始化数据库与 instance 目录的偏移

由于这是另一台机器,数据库文件并不存在,你需要再次执行 init-db 命令在 instance 文件夹中创建数据库:

$ flask --app flaskr init-db

这里有一个容易踩坑的细节:当 Flask 检测到包是“已安装”状态(而非 editable 开发模式)时,它使用不同的目录作为 instance 文件夹。安装模式下,instance 目录位于 .venv/var/flaskr-instance,而不是开发时项目根目录下的 flaskr/instance

这个行为可以直接从 Flask 源码得到印证。Flask 构造函数在 instance_path 未显式给出时,会调用 auto_find_instance_path()(见 src/flask/sansio/app.py):

def auto_find_instance_path(self) -> str:
    prefix, package_path = find_package(self.import_name)
    if prefix is None:
        return os.path.join(package_path, "instance")
    return os.path.join(prefix, "var", f"{self.name}-instance")

(见 src/flask/sansio/app.py

关键判断在 find_package 中(src/flask/sansio/scaffold.py):

  • 若包安装在系统或虚拟环境中(能定位到 prefix/lib/.../site-packages 这样的标准目录层级),返回该虚拟环境的 prefix,于是 instance 目录为 <prefix>/var/<应用名>-instance——对于位于 .venv 中安装的 flaskr,即 .venv/var/flaskr-instance,与文档描述一致;
  • 若包未安装(例如开发时直接从源码目录导入,prefix 为 None),则回退到包路径旁的 instance 子目录,也就是开发模式下教程使用的 flaskr/instance

init-db 命令本身由 examples/tutorial/flaskr/db.py 注册:它执行 current_app.open_resource("schema.sql") 并运行建表脚本,表结构定义在 examples/tutorial/flaskr/schema.sql;而数据库文件路径 flaskr.sqlite 通过 DATABASE=os.path.join(app.instance_path, "flaskr.sqlite") 配置在 examples/tutorial/flaskr/init.py 中——正因数据库落在 instance 目录内,部署到新机器后必须重新 init-db

配置生产环境的 SECRET_KEY

教程在开头为 SECRET_KEY 给了一个默认值(即 create_appapp.config.from_mapping(SECRET_KEY="dev", ...),见 examples/tutorial/flaskr/init.py)。在生产环境中必须把它换成一段随机字节,否则攻击者可以利用公开的 'dev' 密钥伪造 session cookie,或篡改一切使用 secret key 签名的内容。

可以用下面的命令输出一把随机密钥:

$ python -c 'import secrets; print(secrets.token_hex())'

'192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'

然后把生成的值写入 instance 文件夹中的 config.py——应用工厂会在该文件存在时读取它:

# .venv/var/flaskr-instance/config.py
SECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'

你可以在这里设置任何需要的其他配置项,不过对 Flaskr 而言只有 SECRET_KEY 是必须的。

这段“放在 instance 目录、按需加载”的机制在源码中对应两处代码:

  1. 根路径指向 instance 目录Flask(__name__, instance_relative_config=True)examples/tutorial/flaskr/init.py)会让 config 对象以 instance_path 作为 root_path(见 src/flask/sansio/app.py),因此 from_pyfile("config.py") 解析出的正是 <instance 目录>/config.py
  2. 静默加载:工厂函数调用 app.config.from_pyfile("config.py", silent=True)examples/tutorial/flaskr/init.py)。silent=True 的含义可以在 Config.from_pyfile 的实现中看到:当文件不存在时,捕获 OSError 中的 ENOENT/EISDIR/ENOTDIR 错误并静默返回 False,而不是抛出异常(见 src/flask/config.py)。这保证了应用在没有部署者配置文件的机器上也能以默认值启动——只是别忘了,那样 SECRET_KEY 就还是不安全的 'dev'

使用生产 WSGI 服务器运行

在对外公开运行时,不要使用内置开发服务器(flask run。开发服务器由 Werkzeug 提供,图的是开发便利,而非效率、稳定性或安全性。应当使用生产 WSGI 服务器,例如 Waitress:

先在该虚拟环境中安装它:

$ pip install waitress

然后需要告诉 Waitress 你的应用在哪里。它不像 flask run 那样使用 --app 选项,而是要用 --call 指定“导入并调用应用工厂”得到应用对象:

$ waitress-serve --call 'flaskr:create_app'

Serving on http://0.0.0.0:8080

module:callable 的语法等价于执行 from flaskr import create_app; create_app()。由于 Flaskr 采用应用工厂模式(create_app 定义在 examples/tutorial/flaskr/init.py),--call 正是适配工厂模式的方式。对比来看,Flask 自带的 CLI 则通过 -A/--app 选项定位应用(见 src/flask/cli.py--app 参数定义),两者机制不同,部署时不要混用。

Flask 的部署文档对 Waitress 的使用还有几处值得注意的补充(见 docs/deploying/waitress.rst):

  • waitress-serve 唯一的必选参数就是应用定位方式,{module}:{app}--call {module}:{factory} 二选一;
  • --host 127.0.0.1 可把服务仅绑定到本机回环地址;
  • 每条请求的日志默认不打印,只显示错误日志;日志配置需要通过 Python 接口而非命令行完成;
  • Waitress 不应以 root 运行(否则应用代码将以 root 执行),这意味着它无法直接绑定 80/443 端口,前面通常要再加一层 nginx 或 Apache 反向代理;若不指定 --host,会绑定到所有外部 IP 的非特权端口——在使用反向代理时不要这样做,否则可能绕过代理。

教程同时强调:docs/deploying/index.rst 列出了许多不同的托管方式,Waitress 只是教程选用的一个例子,之所以选它,是因为它同时支持 Windows 和 Linux。根据你的项目需求,还有更多 WSGI 服务器与部署选项可以选用。

小结

本部署流程的四步——python -m build --wheel 构建分发包、pip 安装 wheel 并 flask --app flaskr init-db 初始化数据库、在 .venv/var/flaskr-instance/config.py 中写入随机 SECRET_KEY、用 waitress-serve --call 'flaskr:create_app' 启动生产服务器——构成了一条与服务器无关的通用交付路径。理解其中的两个源码细节(auto_find_instance_path 对已安装包与开发包的分支处理、from_pyfile(..., silent=True) 的静默加载语义)后,你可以把同样的模式套用到任何采用应用工厂 + instance 配置的 Flask 项目上,并按项目实际情况替换为 docs/deploying/index.rst 中列出的其他托管方案。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
981
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384