群晖最新版(DSM 7.2) 下使用 Web Station 部署 flask 项目

0. 需求由来

为了在 DSM 7.2 版本下的群晖 NAS 里运行我基于 flask 3.0.2 编写的网页应用程序,我上网查了非常多资料,也踩了很多坑。最主要的就是 7.2 版本的界面与旧版略有不同,而网络上的资料大多基于旧版界面,且大部分仅仅说明了 How to do,而没有解释 Why to do。因此本人随手记录一下。

1. 新建虚拟环境

最开始的一步,自然是建设虚拟环境,用以支撑 Flask 的项目运行:

  1. 从自己的 Flask 项目中导出所需的软件包: pip freeze > requirements.txt
  2. 在 DSM 的管理界面下:web station ➡️ 脚本语言设置 ➡️ python ➡️ 新增 ➡️ 名称 设为 flask_venv ➡️ uWSGI 可保持默认 ➡️ 模块页面,点击上传 requirements.txt

本步骤要点:

  1. DSM 7.2 里的 web station,其脚本语言设置,其实就是搭建一个可以复用的虚拟环境。
  2. 无需自行远程登录 DSM 去手动安装 pip。自 python 3.4 版本以来,pip 已经被内置到官方版本内部了,仅需一个 python -m ensurepip --upgrade 命令,完整安装的 python 即可离线安装好 pip。因此,我们在 DSM 上面的配置过程,全程无需后台登录操作,仅需在 web 页面下足以。

2. 上传代码

上传代码到 DSM 有很多种方式,最简单的是通过 File Station 的 web 界面,将项目代码拖进去,比如 web 下的一个子目录。也可以通过开启 DSM 的 ftp、sftp 等协议进行上传

关于 flask 的代码有一个注意点,即若 flask 的实例是采用工厂模式创建的,则必须添加一个独立的文件,名称随意(一般叫 wsgi.py),内容如下:

python 复制代码
from hello import create_app
app = create_app()

本步骤要点:

  1. 需要对 wsgi 协议有一定了解,知道 wsgi 的程序跑起来需要哪些设置,特别是工厂模式下的 flask 如何支持 wsgi 需要了解。
  2. DSM 下的 sftp 服务,其根目录就是 File Station 见到的根目录,可以依据此设置自动脚本,实现文件的自动上传,以便后期部署过程中的不断修正。为确保安全,建议使用公钥体系,避免使用密码,不赘述。

3. 设置网页服务

设置网页服务: web station ➡️ 网页服务 ➡️ 新增 ➡️ 本机脚本语言网站服务 项选择 python3.9 以及 flask_venv ➡️ 文档根目录 指向第2步上传的代码所在目录,指定 wsgi 文件及 Callable

本步骤要点:

  1. wsgi 文件:即 flask 的主程序所在的 python 文件,一般就是初始化了 Flask 对象的那个。若是工厂模式,则指定前述新增的那个 wsgi.py 文件
  2. Callable:即 wsgi 文件中,代表被初始化的 Flask 对象的那个变量,一般都是 app
  3. 需要理解,DSM 语境下的网页服务,实际意思就是基于虚拟环境与代码实现的一套网页应用。到了这一步,代码其实已经运行起来了,只是尚未对外提供服务而已(详见 /usr/local/etc/nginx/sites-enabled)。DSM 使用 uwsgi 支持 python,并通过 nginx 反向代理,对外提供服务。

4. 对外提供服务

现在到了最后一步,我们需要设置网络门户,以便我们可以面向互联网提供我们前面配置好的网页服务:web station ➡️ 网络门户 ➡️ 网页服务门户

  • 服务:选择我们刚新增的那个 flask 网页服务
  • 门户类型:有三个选择,分别是基于端口、基于名称,和别名门户。
    • 若是只有一个域名,一般选择基于端口,然后选择一个不冲突的端口即可。
    • 若拥有额外的域名,则此时可以选择基于名称并复用 80/443 端口,且要确保该域名设置了正确的解析,指向 NAS 的公网地址。
    • 至于别名门户 ,就是在 URL 末端用一个子目录,指向你的网站。比如我们如果设置了名称为 myapp 的别名,则访问地址可能为 yourname.synology.me/myapp (前面的 yourname.synology.me 依据你注册使用的地址不同而略有不同)。
      如果要使用这一项,则必须确保你的 flask 项目能够部署在子目录,比如我通过利用 functools.wraps 强制重写 flask.url_for 函数,实现硬编码的 url 子目录前缀,最终实现 flask 项目部署的子目录化。(关于如何强制重写 flask.url_for 函数,另文描述)

我个人倾向于使用别名门户,看起来正经,而且无需额外的域名,使用群晖自带的服务即可。

若是出现 Internal Server Error 的错误提示,则一般都是你的 flask 代码有问题,在本地测试修改,并确认第1步建立的虚拟环境内的各模块正确,一般都可以解决了。

至此,flask 应用已经正常跑起来了。

参考

相关推荐
半熟的皮皮虾1 天前
又重新写了个PDF工具箱-转换office格式/合并/拆分/删除常见操作都有了
python·程序人生·pdf·flask·开源·json·学习方法
Kagol1 天前
深入浅出 TinyEditor 富文本编辑器系列2:快速开始
前端·typescript·开源
ASD123asfadxv1 天前
【技术实践】基于YOLO11-Seg与DySnakeConv的14种杂草智能识别系统
python
木土雨成小小测试员1 天前
Python测试开发之前端二
javascript·python·jquery
小二·1 天前
Python Web 开发进阶实战:Flask-Login 用户认证与权限管理 —— 构建多用户待办事项系统
前端·python·flask
两万五千个小时1 天前
Claude Code 中的子 Agent 派生实现:Task Tool 完全指南
人工智能·python
浩瀚之水_csdn1 天前
python字符串解析
前端·数据库·python
liu****1 天前
机器学习-特征降维
人工智能·python·机器学习·python基础·特征降维
全栈小51 天前
【前端】在JavaScript中,=、==和===是三种不同的操作符,用途和含义完全不同,一起瞧瞧
开发语言·前端·javascript
程序猿阿伟1 天前
《Python生态事件溯源与CQRS轻量化落地指南》
大数据·python·微服务