【实用的开源工具】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,所有数据都会放在这里,请妥善保存):
mkdir ~/halo && cd ~/halodocker-compose.yaml。这是官方“Halo + PostgreSQL(推荐)”的写法,我改了三处:镜像换成社区版 halohub/halo;把 8090 端口绑定到 127.0.0.1,给反向代理用;数据库密码和外部地址换成了占位符:
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;。
启动并看日志:
docker compose up -d
docker compose logs -f只想体验的话:单容器 + H2
官方文档里的单容器写法默认使用自带的 H2 数据库,官方明确说只适合体验和测试。README 里的快速体验命令是:
docker run -d --name halo -p 8090:8090 -v ~/.halo2:/root/.halo2 halohub/halo:2.27-v 后面的 /root/.halo2 不能改,官方说这是工作目录映射;不要漏掉这个映射,否则容器一删数据就没了。
第一次使用:初始化页面
- 浏览器访问
/console,首次启动会进入初始化页面。 - 官方提示:如果要用域名访问,建议先配好反向代理和域名解析,再做初始化;通过
http://ip:端口访问不了时,要检查云厂商安全组和 Linux 面板里的防火墙。 - 初始化表单有这些项:语言(Console、个人中心和系统页面的默认语言);外部访问地址(站点对外的完整地址,例如
https://www.example.com,Halo 会按当前请求自动填写,要确认协议、域名和端口正确);站点标题;用户名、电子邮箱、密码(初始管理员);确认密码。点“初始化”即可完成,随后进入 Console。 - 初始化后如果登录状态失效,可以用刚才设置的用户名(或已验证的邮箱)和密码重新登录。
- 官方的“第一篇文章”文档说明:Halo 安装后默认有一篇 “Hello Halo” 文章。在仪表盘点“创建文章”进入编辑页,写完点右上角“发布”,设置标题、别名、分类标签,再点发布。站点首页的样子由当前启用的主题决定。
反向代理
官方提示:Halo 目前不支持代理到子目录;生产环境可以用 Nginx、Caddy 之类。官方文档给了 Nginx、Caddy 2 和 Traefik 的示例,还有 Nginx Proxy Manager 的单独教程。
Nginx。官方示例只写了 80 端口。下面把官方的 listen 80、listen [::]:80 两行去掉,域名换成了 halo.example.com,并加了 HTTPS 的 listen 和证书三行(标了“我加的”),其余保持官方写法:
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(官方示例就三行):
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 文档):
- 先备份。官方说“可选,但推荐”,用 Console 里的备份功能(见下面)。
- 修改
docker-compose.yaml里的镜像版本,例如把halohub/halo:2.27改成新版本。 - 执行
docker compose up -d。
单容器的更新做法:拉新镜像,docker stop halo、docker rm halo,用同样的参数和同一个 ~/.halo2 目录重新创建容器。升级前请自己看一下新版本的发布说明(这是我的建议)。
备份与恢复(官方“备份与恢复”文档):
- 在 Console 左侧菜单“备份”页点“创建备份”,备份请求在后台异步执行,要等一会儿才能看到结果。
- 恢复不限制部署方式和数据库类型,也就是说可以从 PostgreSQL 的站点恢复到别的数据库的新站点。恢复有三种方式:上传备份文件、远程 URL 恢复,以及从工作目录的
backups目录选择备份文件(备份文件大的话官方建议用这种)。 - 官方的注意事项:恢复过程中,已有数据不会被清理,但冲突的数据会被覆盖;恢复完成后会提示重启 Halo,如果没有设置自动重启,需要手动启动。
- 备份不包含商城版的商城数据,用了商城功能的话官方建议直接备份数据库。自动备份与云端同步的“备份增强”插件是付费版专享。
- 我的建议:Console 备份之外,也定期整个打包
~/halo目录(含数据库目录),并保存在另一台机器上。
卸载(通用做法,不是官方文档的说法):docker compose down 只会停止并删除容器,~/halo 下的 halo2 和 db 目录里的数据还在。确认不再需要数据后再手动删除这些目录,删之前先备份。
踩坑清单
- 不支持云虚拟主机,也不支持代理到子目录。 官方环境要求里明确写了这两点,需要独立的服务器和域名(或子域名)。
- 别在生产环境用默认的 H2。 官方警告:可能因为操作不当导致数据文件损坏;必须用的话,要按时备份。有条件就用 Compose 里的 PostgreSQL。
- 先配反向代理和域名,再做初始化。 官方在 Compose 和 Docker 文档里都这么提醒;初始化页面里“外部访问地址”也会自动按当前请求填写,要确认协议、域名和端口。
halo.external-url要写实际访问地址。 官方说如果需要在公网访问,就要配置为实际地址;用 HTTPS 就写https://。- 数据库密码在两个地方,要一致。 Compose 里的
spring.r2dbc.password要和数据库容器的POSTGRES_PASSWORD保持一致(MySQL 方案对应MYSQL_ROOT_PASSWORD)。官方示例里的密码是公开的示例值,一定要换。 - 别漏掉
/root/.halo2的目录映射。 官方工作目录里放着db、themes、plugins、attachments、logs、backups等内容;Docker 部署忘了映射,数据就留不下来。 - 社区版镜像不能激活许可证。
halohub/halo不包含任何付费功能,也不支持激活许可证;要用付费功能需要换成halohub/halo-pro,并按官方“许可证激活”文档操作。官方文档的示例默认是halo-pro,照抄会装成付费版镜像。 - 上传附件报 413。 是反向代理的上传大小限制导致的,官方 FAQ 建议在 Nginx 的
server里加client_max_body_size 1024m;。 - 内存别给太小。 官方建议至少 1G RAM,Compose 里 JVM 默认是
-Xmx256m -Xms256m,可以通过JVM_OPTS调整;如果服务器内存吃紧,官方也提到过“内存不足以运行独立数据库”才用 H2 的情况,但那样要更勤快地备份。 - 主题可能依赖第三方资源。 官方说 Halo 可以在无公网环境下用,但部分主题用了第三方资源(比如公共 CDN),不稳定时会拖慢加载;这类主题需要自己改。
- 第三方主题和插件要看来源。 官方文档对非官网应用市场的安装有安全提醒。装之前看一下作者和更新记录。
- 忘记密码: 官方 FAQ 的顺序是:管理员配置了邮件通知且你验证过邮箱,就用登录页的“找回密码”;否则找有用户管理权限的管理员重置;都没有的话,才通过更新数据库记录来重置,官方给了 SQL,用完要马上改成安全的密码。
- Docker 发布的端口会绕过 ufw 之类的防火墙。 这是通用经验,不是 Halo 文档的说法。所以示例里把 8090 绑定到
127.0.0.1;官方示例是对所有网卡开放的。
出处
有想法或问题?去留言板留言 →