【实用的开源工具】Halo:用 Docker 搭一个能换主题、装插件的建站系统

阅读约 12 分钟
【实用的开源工具】Halo:用 Docker 搭一个能换主题、装插件的建站系统

「实用的开源工具」系列:我只收集值得用的开源项目,写清楚它能做什么、怎么部署、有哪些坑,并在文末标明出处。内容整理自官方文档,核对日期 2026-10-31,具体版本以官方为准。文中的命令都是照官方文档整理的,上线前请先在一台测试机上走一遍。

项目信息卡

项目说明
名称Halo(2.x)
做什么开源建站工具:个人博客、知识库、企业官网等,用主题决定外观,用插件扩展功能
许可证社区版 GPL-3.0(仓库 LICENSE 与 README 一致,官方文档也写明 GPL-3.0)
仓库github.com/halo-dev/halo
官网与文档halo.run、docs.halo.run
最近版本v2.27.1(2026-10-23 发布,查询于 2026-10-31)
维护状态仓库未归档,2026-10-31 仍有推送
运行方式Docker(推荐)、JAR 文件、Helm、Podman 等;默认端口 8090,后台地址 /console
数据库PostgreSQL、MySQL、MariaDB、H2。官方 Compose 文档推荐 PostgreSQL,不建议生产环境用默认的 H2
内存建议官方写的是“为了获得更好的体验,建议至少配置 1G 的 RAM”
版本区分社区版(开源免费)、付费版(专业版、商城版,商业产品)。两者用不同的 Docker 镜像

它能做什么

  • 内容管理:文章、页面、分类标签、评论、附件管理、菜单,后台叫 Console。
  • 主题:站点外观由当前启用的主题决定。官方说默认主题是 Earth,可以在应用市场安装其他主题。
  • 插件:插件独立于 Halo 核心,可以单独安装、升级、卸载、启用/禁用,用来扩展功能。
  • 内置应用市场:从 Halo 2.10 开始,Console 里内置了应用市场,主题和插件可以直接在里面安装。
  • 备份与恢复:从 Halo 2.8 开始,Console 里可以一键备份和恢复。
  • README 还写了:社区版提供超过 100 款免费主题和插件。

不适合的场景:官方说明 Halo 目前不支持市面上的云虚拟主机,需要云服务器或 VPS;另外它不支持反向代理到子目录(例如 example.com/blog)。

社区版和付费版:镜像不一样

官方文档里有一个容易忽略的细节:

  • 社区版镜像:halohub/halo:<version>,用开源仓库构建,不包含任何付费功能,也不支持激活许可证。
  • 付费版镜像:halohub/halo-pro:<version>,包含专业版和商城版,部分付费功能需要许可证激活。
  • 官方文档的示例默认写的是付费版镜像 halo-pro,如果你装社区版,要把镜像名里的 halo-pro 换成 halo。下面我直接按社区版写。
  • 版本标签遵循 SemVer(主.次.补丁,如 2.27.0),另外还有 :2(Halo 2 的最新版本)、:2.27(2.27 系列的最新版本)这样的标签。官方文档还提供了一个自建的镜像仓库 registry.fit2cloud.com/halo/halo,国内拉取慢的时候可以用。

部署前要准备什么

  • 云服务器或 VPS,装好 Docker 和 Docker Compose。
  • CPU 官方说无特别要求(镜像支持多平台);内存建议至少 1G;磁盘只要不大量上传附件要求不高,官方推荐 SSD。
  • 网络:Halo 可以在无公网环境下运行,但部分主题引用了第三方资源,可能需要公网。
  • 如果用 JAR 文件部署,官方写的 Java 版本要求:2.21 及以上版本用 JRE 21,2.20 及以下用 JRE 17。用 Docker 镜像则不需要在服务器上装 JRE。
  • 域名和 HTTPS 证书(下面的 halo.example.com 请换成自己的)。

部署(Docker Compose + PostgreSQL)

先建目录(官方示例用 ~/halo,所有数据都会放在这里,请妥善保存):

bash
mkdir ~/halo && cd ~/halo

docker-compose.yaml。这是官方“Halo + PostgreSQL(推荐)”的写法,我改了三处:镜像换成社区版 halohub/halo;把 8090 端口绑定到 127.0.0.1,给反向代理用;数据库密码和外部地址换成了占位符:

yaml
services:
  halo:
    image: halohub/halo:2.27
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./halo2:/root/.halo2
    ports:
      - "127.0.0.1:8090:8090"
    healthcheck:
      test:
        ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    environment:
      # JVM 参数,官方说明默认为 -Xmx256m -Xms256m,置空表示不添加 JVM 参数
      - JVM_OPTS=-Xmx256m -Xms256m
    command:
      - --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo
      - --spring.r2dbc.username=halo
      # 必须与下面 halodb 的 POSTGRES_PASSWORD 一致
      - --spring.r2dbc.password=改成你的数据库密码
      - --spring.sql.init.platform=postgresql
      # 外部访问地址,改成你的实际域名
      - --halo.external-url=https://halo.example.com/
  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=改成你的数据库密码
      - POSTGRES_USER=halo
      - POSTGRES_DB=halo
      - PGUSER=halo

networks:
  halo_network:

说明:

  • 镜像标签:我用了 2.27(官方示例的写法,对应 2.27 系列的最新版)。我查过 Docker Hub,halohub/halo 上有 2.27、2.27.1 和 2 这几个标签;想更严格地固定版本,就写具体的补丁版本,写之前去 Docker Hub 确认标签存在。
  • 官方说明 PostgreSQL 容器默认没有做端口映射,需要外部访问数据库时再自己加 5432。
  • 官方还提供了 “Halo + MySQL”(mysql:8.1.0)、“Halo + H2” 和“使用外部数据库”三种 Compose 写法。运行参数里的 spring.sql.init.platform 支持 postgresql、mysql、mariadb、h2。
  • 使用外部数据库时,需要提前手动建库,官方给的 MySQL 示例是 create database halo character set utf8mb4 collate utf8mb4_bin;。

启动并看日志:

bash
docker compose up -d
docker compose logs -f

只想体验的话:单容器 + H2

官方文档里的单容器写法默认使用自带的 H2 数据库,官方明确说只适合体验和测试。README 里的快速体验命令是:

bash
docker run -d --name halo -p 8090:8090 -v ~/.halo2:/root/.halo2 halohub/halo:2.27

-v 后面的 /root/.halo2 不能改,官方说这是工作目录映射;不要漏掉这个映射,否则容器一删数据就没了。

第一次使用:初始化页面

  1. 浏览器访问 /console,首次启动会进入初始化页面。
  2. 官方提示:如果要用域名访问,建议先配好反向代理和域名解析,再做初始化;通过 http://ip:端口 访问不了时,要检查云厂商安全组和 Linux 面板里的防火墙。
  3. 初始化表单有这些项:语言(Console、个人中心和系统页面的默认语言);外部访问地址(站点对外的完整地址,例如 https://www.example.com,Halo 会按当前请求自动填写,要确认协议、域名和端口正确);站点标题;用户名、电子邮箱、密码(初始管理员);确认密码。点“初始化”即可完成,随后进入 Console。
  4. 初始化后如果登录状态失效,可以用刚才设置的用户名(或已验证的邮箱)和密码重新登录。
  5. 官方的“第一篇文章”文档说明:Halo 安装后默认有一篇 “Hello Halo” 文章。在仪表盘点“创建文章”进入编辑页,写完点右上角“发布”,设置标题、别名、分类标签,再点发布。站点首页的样子由当前启用的主题决定。

反向代理

官方提示:Halo 目前不支持代理到子目录;生产环境可以用 Nginx、Caddy 之类。官方文档给了 Nginx、Caddy 2 和 Traefik 的示例,还有 Nginx Proxy Manager 的单独教程。

Nginx。官方示例只写了 80 端口。下面把官方的 listen 80、listen [::]:80 两行去掉,域名换成了 halo.example.com,并加了 HTTPS 的 listen 和证书三行(标了“我加的”),其余保持官方写法:

nginx
upstream halo {
  server 127.0.0.1:8090;
}
server {
  listen 443 ssl;                                # 我加的
  ssl_certificate     /path/to/fullchain.pem;    # 我加的
  ssl_certificate_key /path/to/privkey.pem;      # 我加的
  server_name halo.example.com;
  client_max_body_size 1024m;
  location / {
    proxy_pass http://halo;
    proxy_set_header HOST $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

Caddy 2(官方示例就三行):

text
halo.example.com

encode gzip

reverse_proxy 127.0.0.1:8090

要点:

  • client_max_body_size 要够大,否则上传附件会报 413 Request Entity Too Large;官方 FAQ 的建议值是 1024m,不够就自己调大。
  • halo.external-url 要和你实际访问的地址一致。官方配置说明里还有 halo.use-absolute-permalink(永久链接是否生成为绝对地址,默认 false),设成 true 时要确保 halo.external-url 配置正确。
  • 官方配置说明里,Halo 监听端口是 server.port,默认 8090。

主题与插件

  • 主题:在 Console 的“主题”页,点右上角“主题管理”可以安装、切换主题。有三种安装方式:内置应用市场(推荐)、本地上传主题压缩包、远程下载地址。选中主题不等于启用,要点右上角的“启用”才生效。 还可以预览主题而不改变当前启用的主题;卸载分“卸载”和“卸载并删除配置”两种。
  • 插件:在插件管理页点右上角“安装”,同样有应用市场、本地上传、远程下载三种方式。可以启用/禁用、升级、重置设置、卸载;从 Halo 2.24 开始,已启用的插件可以“重载”而不用重启 Halo。
  • 获取渠道:官方列出两个渠道,应用市场 halo.run/store/apps 和社区整理的 Awesome Halo。
  • 安全:官方明确提醒,从非 Halo 官网应用市场安装主题或插件要注意其安全性。
  • 搜索引擎、扩展点等:Halo 默认提供 Lucene 搜索引擎;装了其他搜索引擎插件(官方举的例子是 Meilisearch)之后,要在插件管理的“扩展配置”里选择用哪一个。

更新与卸载

更新(官方 Docker Compose 文档):

  1. 先备份。官方说“可选,但推荐”,用 Console 里的备份功能(见下面)。
  2. 修改 docker-compose.yaml 里的镜像版本,例如把 halohub/halo:2.27 改成新版本。
  3. 执行 docker compose up -d。

单容器的更新做法:拉新镜像,docker stop halo、docker rm halo,用同样的参数和同一个 ~/.halo2 目录重新创建容器。升级前请自己看一下新版本的发布说明(这是我的建议)。

备份与恢复(官方“备份与恢复”文档):

  • 在 Console 左侧菜单“备份”页点“创建备份”,备份请求在后台异步执行,要等一会儿才能看到结果。
  • 恢复不限制部署方式和数据库类型,也就是说可以从 PostgreSQL 的站点恢复到别的数据库的新站点。恢复有三种方式:上传备份文件、远程 URL 恢复,以及从工作目录的 backups 目录选择备份文件(备份文件大的话官方建议用这种)。
  • 官方的注意事项:恢复过程中,已有数据不会被清理,但冲突的数据会被覆盖;恢复完成后会提示重启 Halo,如果没有设置自动重启,需要手动启动。
  • 备份不包含商城版的商城数据,用了商城功能的话官方建议直接备份数据库。自动备份与云端同步的“备份增强”插件是付费版专享。
  • 我的建议:Console 备份之外,也定期整个打包 ~/halo 目录(含数据库目录),并保存在另一台机器上。

卸载(通用做法,不是官方文档的说法):docker compose down 只会停止并删除容器,~/halo 下的 halo2 和 db 目录里的数据还在。确认不再需要数据后再手动删除这些目录,删之前先备份。

踩坑清单

  1. 不支持云虚拟主机,也不支持代理到子目录。 官方环境要求里明确写了这两点,需要独立的服务器和域名(或子域名)。
  2. 别在生产环境用默认的 H2。 官方警告:可能因为操作不当导致数据文件损坏;必须用的话,要按时备份。有条件就用 Compose 里的 PostgreSQL。
  3. 先配反向代理和域名,再做初始化。 官方在 Compose 和 Docker 文档里都这么提醒;初始化页面里“外部访问地址”也会自动按当前请求填写,要确认协议、域名和端口。
  4. halo.external-url 要写实际访问地址。 官方说如果需要在公网访问,就要配置为实际地址;用 HTTPS 就写 https://。
  5. 数据库密码在两个地方,要一致。 Compose 里的 spring.r2dbc.password 要和数据库容器的 POSTGRES_PASSWORD 保持一致(MySQL 方案对应 MYSQL_ROOT_PASSWORD)。官方示例里的密码是公开的示例值,一定要换。
  6. 别漏掉 /root/.halo2 的目录映射。 官方工作目录里放着 db、themes、plugins、attachments、logs、backups 等内容;Docker 部署忘了映射,数据就留不下来。
  7. 社区版镜像不能激活许可证。 halohub/halo 不包含任何付费功能,也不支持激活许可证;要用付费功能需要换成 halohub/halo-pro,并按官方“许可证激活”文档操作。官方文档的示例默认是 halo-pro,照抄会装成付费版镜像。
  8. 上传附件报 413。 是反向代理的上传大小限制导致的,官方 FAQ 建议在 Nginx 的 server 里加 client_max_body_size 1024m;。
  9. 内存别给太小。 官方建议至少 1G RAM,Compose 里 JVM 默认是 -Xmx256m -Xms256m,可以通过 JVM_OPTS 调整;如果服务器内存吃紧,官方也提到过“内存不足以运行独立数据库”才用 H2 的情况,但那样要更勤快地备份。
  10. 主题可能依赖第三方资源。 官方说 Halo 可以在无公网环境下用,但部分主题用了第三方资源(比如公共 CDN),不稳定时会拖慢加载;这类主题需要自己改。
  11. 第三方主题和插件要看来源。 官方文档对非官网应用市场的安装有安全提醒。装之前看一下作者和更新记录。
  12. 忘记密码: 官方 FAQ 的顺序是:管理员配置了邮件通知且你验证过邮箱,就用登录页的“找回密码”;否则找有用户管理权限的管理员重置;都没有的话,才通过更新数据库记录来重置,官方给了 SQL,用完要马上改成安全的密码。
  13. Docker 发布的端口会绕过 ufw 之类的防火墙。 这是通用经验,不是 Halo 文档的说法。所以示例里把 8090 绑定到 127.0.0.1;官方示例是对所有网卡开放的。

出处

想要类似的东西?网站、Telegram 机器人、运维工具,说说你的需求。
发布需求

有想法或问题?去留言板留言 →