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

0. 需求由来

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

群晖最新版(DSM 7.2) 下使用 Web Station 部署 flask 项目_第1张图片

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),内容如下:

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 项目能够部署在子目录,比如我通过重写 flask.url_for 函数,实现 url 子目录前缀,最终实现 flask 项目部署的子目录化。(关于如何重写 flask.url_for 函数,另文描述)

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

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

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

参考

  • flask 官方文档: https://flask.palletsprojects.com/en/3.0.x/
  • ensurepip 的官方文档: https://docs.python.org/zh-cn/dev/library/ensurepip.html
  • 群晖nas中使用python的Flask框架搭建网站(用Web Station): https://www.cnblogs.com/yaoyue68/p/17587070.html
  • 群晖NAS中Web Station使用Flask作为后端服务教程: https://www.bilibili.com/read/cv17483317/

你可能感兴趣的:(运维,python,nas,前端,flask,python)