在群晖 NAS 上用 Docker 部署 Halo

3 阅读

折腾过 NAS 的人大概都有这个习惯:新的服务先不买云服务器,先在自己的群晖上跑起来试试。Halo 完全支持 Docker 部署,而群晖 DSM 7.2 开始把 Docker 套件改名叫了 Container Manager,界面有些变化,但用法基本一致。

这篇文章记录在群晖上部署 Halo 的完整流程,包括数据库配置、网络设置和反向代理。如果你的群晖还在用 DSM 6.x 或 7.0/7.1 的 Docker 套件,流程大同小异,可以直接参考。


一、部署前的准备

硬件要求

群晖机型没有硬性要求,有 Docker 支持即可。为了让后台访问、插件运行和图片处理等操作更稳定,建议给 Halo 预留足够的运行资源:

  • 最低建议预留 2GB 可用内存(NAS 本身也要占一部分,所以总内存建议 4GB 以上)。
  • 推荐 4GB+ 可用内存,后台操作和插件运行会更从容。
  • 如果你的群晖配置较低,可以先减少同时运行的其他容器,后续再根据访问量调整。

需要安装的套件

打开群晖「套件中心」,先搜索并安装 Container Manager:

套件作用
Container ManagerDocker 容器管理(旧版叫 Docker)

群晖套件中心 - Container Manager

如果你只使用后面的推荐方案 A,不需要安装数据库套件。只有准备尝试方案 B(Halo 连接群晖 MariaDB 10)时,再安装以下两个套件:

套件作用
MariaDB 10数据库服务
phpMyAdmin数据库可视化管理工具

安装 phpMyAdmin 时,套件中心会提示安装 Web Station、PHP、Apache HTTP Server 等依赖,按提示确认即可;不同 DSM 或套件版本显示的依赖项可能略有差异。


二、可选:配置 MariaDB 数据库(方案 B 需要)

如果你准备使用后面的方案 A,可以跳过本节。Halo 官方 Docker Compose 文档使用 PostgreSQL 作为示例数据库;群晖 MariaDB 10 只建议在你确认 Docker 容器可以访问套件数据库后再使用。

第一步:初始化 MariaDB

打开 MariaDB 10 套件,首次运行时会提示设置 root 密码。设一个自己能记住的强密码,记录下来。这个密码不要和后面的 Halo 用户密码相同。

群晖套件中心 - MariaDB 设置密码

第二步:创建 Halo 专用数据库和用户

打开 phpMyAdmin,用 root 账户登录(用户名 root,密码是上一步设置的)。

点击顶部导航栏的「用户账户」,然后点击「新增用户账户」:

phpMyAdmin 创建用户

填写以下信息:

  • 用户名:填 halo
  • 主机名:选择「任意主机」,即 %(这样数据库用户才允许来自 Docker 网络的连接,但还需要确认 MariaDB 端口本身可以被容器访问)
  • 密码:点击「生成」按钮随机生成一个强密码,复制下来保存好,后面 docker-compose 配置里要用
  • 勾选「创建与用户同名的数据库并授予所有权限」——这一步会自动创建名为 halo 的数据库,并授权给这个用户

点击「执行」完成。


三、准备部署目录

群晖的 Docker 数据需要存放在共享文件夹中。打开 File Station,进入 docker 共享文件夹(如果没有就新建一个),在里面创建一个 halo 子文件夹:

docker/
└── halo/          
└──── halo2/      // 同时创建 Halo 数据目录
└──── db/         // 同时创建 PostgreSQL 数据库目录(如果使用方案 A)

群晖文件管理

右键点击 halo 文件夹 → 「属性」→ 「权限」,确保当前用户对这个文件夹有读写权限。一般默认就有,不必额外操作。


四、编写 docker-compose 配置

这里提供两种配置方案。优先使用方案 A;方案 B 需要先确认 Halo 容器能访问群晖 MariaDB 10。

方案 A:Halo + 内置 PostgreSQL 容器(推荐)

如果你懒得折腾数据库,最简单的方案是让 Docker Compose 自己拉一个 PostgreSQL 容器。Halo 和 PostgreSQL 都在 Docker 里通过内部网络通信,不依赖群晖的外部套件。

打开 Container Manager → 左侧「项目」→ 点击「新增」。项目名称填 halo,路径选择刚才创建的 /docker/halo,来源选「创建 docker-compose.yml」,在编辑框中填入:

services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.25
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./halo2:/root/.halo2
    ports:
      - "8090:8090"
    environment:
      - JVM_OPTS=-Xmx256m -Xms256m
    command:
      - --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo
      - --spring.r2dbc.username=halo
      - --spring.r2dbc.password=openpostgresql
      - --spring.sql.init.platform=postgresql
      - --halo.external-url=http://你的群晖IP:8090/

  halodb:
    image: postgres:15.4
    restart: on-failure:3
    networks:
      halo_network:
    volumes:
      - ./db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready"]
      interval: 10s
      timeout: 5s
      retries: 5
    environment:
      - POSTGRES_PASSWORD=openpostgresql
      - POSTGRES_USER=halo
      - POSTGRES_DB=halo
      - PGUSER=halo

networks:
  halo_network:

注意:把 external-url 中的 你的群晖IP 替换为群晖在内网的 IP 地址,比如 http://192.168.1.100:8090/。这个地址不能是 localhost127.0.0.1

方案 B:连接群晖 MariaDB 10(可选)

如果你想把数据库放在群晖套件里统一管理,可以尝试这个方案。但它依赖 MariaDB 10 套件允许 Docker 容器通过 TCP 访问。部分 DSM、MariaDB 套件或网络配置下,容器即使填写群晖内网 IP,也可能连不上数据库。

继续使用方案 B 前,先确认三件事:

  • MariaDB 10 的实际监听端口,常见是 33063307
  • halo 数据库用户的主机名不是只允许 localhost,需要允许来自 Docker 网络的连接。
  • Halo 容器所在的网络可以访问 群晖IP:数据库端口。如果这一步不通,建议直接改用方案 A。

确认可达后,可以参考下面的配置。把示例中的 192.168.1.1003307 和密码改成你的实际值:

services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.25
    container_name: halo
    restart: on-failure:3
    networks:
      halo_network:
    ports:
      - "8090:8090"
    volumes:
      - ./halo2:/root/.halo2
    environment:
      - JVM_OPTS=-Xmx256m -Xms256m
    command:
      - --spring.r2dbc.url=r2dbc:pool:mariadb://192.168.1.100:3307/halo
      - --spring.r2dbc.username=halo
      - --spring.r2dbc.password=你创建的halo用户密码
      - --spring.sql.init.platform=mariadb
      - --halo.external-url=http://192.168.1.100:8090/

networks:
  halo_network:

关键点

  • spring.r2dbc.url 中的 192.168.1.100 是你群晖的内网 IP。不能写 localhost127.0.0.1——容器内部有自己的网络,localhost 指向的是容器自己,不是群晖主机。
  • MariaDB 默认端口是 3306,但如果群晖上之前装了其他 MariaDB 版本的套件,端口可能变成了 3307。在 MariaDB 10 套件设置中可以查看实际端口。
  • 如果 Halo 启动日志里出现连接超时、连接被拒绝,或容器内无法访问 MariaDB 端口,不要继续反复改密码;先改用方案 A,或者再单独排查群晖 MariaDB 的远程访问、防火墙和 Docker 网络。
  • spring.sql.init.platformmariadb 而不是 mysql

五、启动 Halo

在 Container Manager 编辑完 docker-compose.yml 后,点击「下一步」,然后「完成」。Container Manager 会自动拉取镜像并启动容器。

群晖 Container Manager 运行 Halo

首次启动需要拉取镜像,根据网络速度可能需要几分钟。可以在「容器」标签页中看到 halo 容器的状态,等它变成绿色「运行中」即可。

如果想看启动日志,在容器上右键 → 「详情」→ 「日志」标签页。


六、初始化 Halo

容器启动成功后,打开浏览器访问 http://你的群晖IP:8090,会看到 Halo 的初始化页面:

Halo 初始化页面

按提示设置站点名称和管理员账号密码,完成初始化后进入后台。如果初始化时填写的站点地址和你后续使用的域名或 IP 不一致,后面可以在后台的「系统设置」中修改。

完成初始化后,再访问 http://你的群晖IP:8090/console 就是 Halo 后台。访问 http://你的群晖IP:8090 是你网站的前台。


七、配置反向代理和域名访问

直接用 IP:8090 访问不太优雅,也不方便记忆。群晖自带反向代理功能,可以把域名 80/443 端口的请求转发到 Halo 的 8090。

打开「控制面板」→ 「登录门户」→ 「高级」→ 「反向代理服务器」→ 点击「新增」:

群晖反向代理新增规则

字段
来源 - 协议HTTPS
来源 - 主机名你的域名(如 blog.example.com
来源 - 端口443
目的地 - 协议HTTP
目的地 - 主机名localhost
目的地 - 端口8090

如果你还没有 SSL 证书,可以先去「控制面板」→ 「安全性」→ 「证书」中申请 Let's Encrypt 免费证书(需要你的域名已配置 DDNS 或指向群晖的公网 IP)。

配置好反向代理之后,别忘了回到 Halo 后台的「概览页面」中,把「外部访问地址」改为 https://你的域名


八、日常管理

升级 Halo

  1. 在 Container Manager 的「项目」中,找到 halo 项目,点击进入。
  2. 在「YAML 配置」标签页中,修改镜像版本号(比如把 halo:2.25 改成你要升级到的目标版本标签)。
  3. 导出备份(Halo 后台 → 系统 → 备份),然后点击「构建」重新拉取镜像并启动。

查看日志

Container Manager → 容器 → 选中 halo → 「详情」→ 「日志」。

停止和重启

在 Container Manager 的「项目」标签页,可以直接对整个项目执行「停止」和「启动」操作。也可以在「容器」标签页单独操作。


九、常见问题

Q:容器启动了但访问不了 8090 端口?

检查两点:第一,群晖的防火墙是否拦截了 8090 端口(控制面板 → 安全性 → 防火墙);第二,是否有其他服务占了 8090 端口。

Q:方案 B 中 Halo 连不上 MariaDB?

先确认 spring.r2dbc.url 里没有写 localhost127.0.0.1。如果已经改成群晖内网 IP 仍然连不上,通常就不是 Halo 配置本身的问题,而是 MariaDB 10 套件的端口监听、数据库用户授权、群晖防火墙或 Docker 网络访问限制。想先把 Halo 跑起来,建议直接使用方案 A 的 PostgreSQL 容器。

Q:NAS 资源有限怎么办?

可以适当调低 JVM_OPTS,比如改成 -Xmx128m -Xms128m。这个配置下 Halo 可以运行,但在大量图片上传、搜索索引或同时启用多个插件的场景下,响应可能会慢一些。

Q:怎么让外网也能访问?

需要你的群晖能通过公网 IP 或 DDNS 访问到。可以用群晖自带的 DDNS 服务(控制面板 → 外部访问 → DDNS),然后在路由器上做 443 端口的端口转发。配合群晖反向代理和 Let's Encrypt 证书,就能实现 HTTPS 公网访问。

Q:数据存在哪?

/docker/halo/halo2/ 是 Halo 的工作目录,包含附件、插件、主题、备份文件等运行数据。文章、用户、站点配置等核心数据在数据库中:如果你用的是方案 A,数据库数据在 /docker/halo/db/ 下;如果你用的是方案 B,数据库数据由群晖 MariaDB 10 套件管理。迁移或手动备份时,需要同时处理 Halo 工作目录和对应的数据库。


评论