首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Halo 博客搭建教程:Docker 部署与主题配置

Halo 博客搭建教程:Docker 部署与主题配置

原创
作者头像
gavin1024
发布于 2026-10-19 17:48:46
发布于 2026-10-19 17:48:46
1620
举报

Halo 是我在给不太熟悉建站的朋友推荐博客程序时,经常会放进候选名单的一个:国产开源、中文文档完整、后台界面清爽,主题和插件都能直接在后台装。但它有两个地方和 PHP 类程序不一样,第一次部署很容易踩坑——它是 Java 应用,内存占用要高一些;它自带的 H2 数据库只适合体验,不适合跑正式站。本文用 Docker 完成部署,重点讲这两个坑怎么避开,以及附件、升级、备份这几件长期运维里的事。

一、Halo 适合什么场景

场景

是否适合

个人博客、写作站

适合

团队的内容发布站

适合

需要商城、会员等复杂业务

建议用功能更完整的方案

追求极致轻量、只写纯文字

可考虑更轻的程序

它的几个特点:后台界面比较现代,操作逻辑清楚,对不熟悉建站的人友好;国产项目,中文文档完整,遇到问题社区交流没有语言障碍;插件化架构,核心保持精简,功能靠插件扩展;主题可以直接在后台安装。

需要提前知道的一点:Halo 用 Java 实现,启动后会占一块内存作为运行空间。同样 1 GB 内存的机器,跑 PHP 博客绰绰有余,跑 Halo 就比较紧张,再加上数据库基本不够用。

二、资源规划与数据库选择

项目

最低配置

建议配置

CPU

1 核

2 核

内存

1 GB

2 GB 及以上

磁盘

20 GB

40 GB

内存我建议直接从 2 GB 起。 1 GB 能起来,但应用和数据库同机时会很吃紧,表现是后台操作卡顿、偶尔启动失败,排查起来还不容易第一时间想到是内存问题。

数据库:不要用 H2 跑正式站

Halo 自带 H2 内嵌数据库,不用额外部署,适合快速体验。但它不适合长期使用——数据量增长后性能和可靠性都有限,官方也建议生产环境使用外部数据库。

这个选择要在一开始就定下来。 先用 H2 跑起来、写了几十篇文章再想换,就得做数据迁移,比一开始直接上 PostgreSQL 或 MySQL 麻烦得多。本文按 PostgreSQL 部署。

前置条件是已经装好 Docker 和 Compose 插件:

代码语言:bash
复制
docker --version
docker compose version

需要放通的端口:22、80、443。

三、部署 Halo

代码语言:bash
复制
mkdir -p ~/apps/halo && cd ~/apps/halo

编写 compose.yaml:

代码语言:yaml
复制
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: halo
      POSTGRES_PASSWORD: 替换为强密码
      POSTGRES_DB: halo
    volumes:
      - pg-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "halo"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  halo:
    image: registry.fit2cloud.com/halo/halo:2.20
    ports:
      - "127.0.0.1:8090:8090"
    volumes:
      - ./halo-data:/root/.halo2
    environment:
      SPRING_R2DBC_URL: r2dbc:pool:postgresql://postgres:5432/halo
      SPRING_R2DBC_USERNAME: halo
      SPRING_R2DBC_PASSWORD: 与上面保持一致
      SPRING_SQL_INIT_PLATFORM: postgresql
      HALO_EXTERNAL_URL: https://blog.example.com/
      TZ: Asia/Shanghai
    depends_on:
      postgres:
        condition: service_healthy
    restart: unless-stopped

volumes:
  pg-data:

这份配置里有四处是我刻意写成这样的:

depends_on 带了健康检查条件。 只写 depends_on 不加条件,Compose 只保证数据库容器先启动,不保证数据库已经能接受连接。Halo 启动又比较快,就会出现"数据库还在初始化,应用已经去连了"的情况,表现是首次启动失败、重启一下又好了——这种时好时坏的问题最难排查。加上 service_healthy 条件就解决了。

数据库地址写的是容器服务名 postgres。 填 localhost 一定连不上,因为在容器里它指向容器自己。

HALO_EXTERNAL_URL 必须填对外的完整地址。 它决定站点生成的链接。填错了,图片链接和跳转地址都会指向错误的位置。

镜像版本固定成具体版本号。 Halo 跨大版本升级有约束,用滚动标签的话,某次拉取镜像就可能悄悄跨了大版本,主题和插件一起不兼容。

./halo-data 存放附件、主题、插件和配置,是必须持久化的数据。

启动:

代码语言:bash
复制
mkdir -p halo-data
docker compose up -d
docker compose ps
docker compose logs -f halo

首次启动要耐心等。 要初始化数据库,Java 应用本身启动也需要一点时间。看到日志里出现启动完成的提示再访问,提前访问看到报错不代表部署失败。

四、配置反向代理与 HTTPS

先在域名服务商处添加 A 记录指向服务器公网 IP,解析生效后验证:

代码语言:bash
复制
dig +short blog.example.com

配置反向代理,以 Caddy 为例:

代码语言:caddyfile
复制
blog.example.com {
    reverse_proxy 127.0.0.1:8090
    request_body {
        max_size 200MB
    }
}

request_body max_size 要按附件的最大体积来设。 默认值偏小,上传稍大的图片或文件会失败,而 Halo 后台只显示"上传失败",看不出是代理层拦的。

服务器位于中国内地、使用域名对外提供服务时,需要先完成 ICP 备案。

如果后来改了访问域名,要同步更新 HALO_EXTERNAL_URL 并重建容器:

代码语言:bash
复制
docker compose down && docker compose up -d

五、初始化与基础设置

访问域名会进入初始化页面:

  1. 创建管理员账号,用户名不要用常见默认值,密码 12 位以上。
  2. 填写站点名称和描述。

进后台后先处理几项:

  • 站点设置:确认地址、标题、描述正确。
  • 评论设置:开评论的话建议同时开审核,垃圾评论来得比你想象的快。
  • 用户管理:多人使用时给每个人建独立账号并分配合适角色,不要共用。

六、主题与插件:先确认版本兼容

Halo 可以直接在后台装主题和插件,比手动上传方便很多。但有一条要特别注意:跨大版本的主题和插件通常不兼容。

装主题前确认它支持你当前的 Halo 版本。装完如果站点出现异常——页面空白、样式错乱——先在后台切回默认主题,站点能恢复就说明是主题的问题。

插件常用的方向:代码高亮、搜索增强、站点地图、评论组件、附件存储对接。装完插件出现异常时,先停用最近装的那个,这是定位最快的方法。

七、把附件放到对象存储

这一项对图片多的博客很值得做。

附件存在服务器本地有两个问题:占磁盘,而且每次被访问都消耗服务器带宽。对接对象存储后,附件存在对象存储里,容量按用量计费,配合内容分发网络分发还能明显减轻带宽压力。

在对象存储控制台创建存储桶,记下名称、地域、访问域名和密钥。

权限设置要分清楚。 博客附件需要被读者公开访问,所以读权限设为公有读;但写权限必须保持私有,上传通过 Halo 用密钥完成。公有读写意味着任何人都能往你的存储桶里传文件,会被拿来放违规内容或者恶意占用空间和流量。

密钥用子账号,只授予这一个存储桶的读写权限,不要用主账号密钥。

在 Halo 后台的附件管理里添加存储策略,选 S3 兼容协议类型,填入存储桶信息。配完上传一张图测试,再去对象存储控制台确认文件确实到了存储桶——只看 Halo 后台显示上传成功是不够的,有可能还在写本地磁盘。

八、上线前验证

验证项

怎么验证

HTTPS 访问

curl -I https://blog.example.com 返回 200 或 302

后台登录

用初始化创建的账号登录

发文章

发一篇测试文章,前台可见

文章详情页

点开文章,渲染正常

附件上传

上传图片并插入文章,正常显示

大文件上传

上传一个接近上限的文件

容器状态

docker compose ps 全部 running,数据库显示健康

移动端

手机打开站点,排版正常

大文件上传这一项要专门测。 用小图测试完全暴露不出请求体大小的限制,等到真要传一张大图时才发现传不上去。

九、常见故障

容器启动失败或反复重启

代码语言:bash
复制
docker compose logs halo --tail 100
docker compose logs postgres --tail 50

三个最常见的原因:数据库连接配置写错、数据库还没就绪应用就启动了、内存不够。内存问题用这两条确认:

代码语言:bash
复制
free -h
docker stats --no-stream

页面能打开但链接指向错误地址:HALO_EXTERNAL_URL 填错了,改完重建容器。

附件上传失败:三处都要查——代理的请求体大小限制、Halo 的附件大小配置、对接对象存储时的密钥权限。

主题装完站点异常:多半是版本不兼容,切回默认主题。

每次重启都很慢:首次启动慢是正常的,如果每次都很慢,看看内存是否吃紧。内存不够会导致频繁换页,整体都会变慢。

十、升级与备份

升级要看版本跨度

Halo 不支持跨多个大版本直接升级。我的升级流程是:

  1. 读目标版本的发布说明,确认有没有不兼容变更。
  2. 备份数据库和挂载目录。
  3. 创建实例快照。
  4. 修改 compose.yaml 里的镜像版本标签。
  5. 执行 docker compose pull 和 docker compose up -d。
  6. 启动后验证文章、附件、主题是否正常。

第 1 步不能跳。主题和插件跟不上新版本是升级后最常见的问题,提前看说明能少踩很多坑。

备份要覆盖两部分

内容

说明

数据库

文章、页面、评论、配置、用户

挂载目录

附件、主题、插件、应用配置

代码语言:bash
复制
docker compose exec -T postgres \
  pg_dump -U halo halo | gzip > ~/halo-db-$(date +%Y%m%d).sql.gz
tar -czf ~/halo-data-$(date +%Y%m%d).tar.gz -C ~/apps/halo halo-data

附件已经放到对象存储的话,挂载目录会小很多,主要是主题和配置。

备份同步到服务器之外,并做一次恢复演练——在另一个环境用备份还原,确认文章、附件、主题设置都在。

变更前建快照:快照回滚会把整块系统盘恢复到快照时间点,之后写入的数据会被清除,运行中的实例会自动关机。回滚前先确认快照之后有没有新发布的内容。

日常维护:每周确认备份成功,关注版本和安全公告,定期清理垃圾评论,留意磁盘和内存水位。

内容方面:文章里用到的图片和引用内容要确认有权使用,转载需获得授权并标注出处;开放评论就要对评论区内容承担管理责任,建议开启审核;不发布违法违规内容。

Halo 部署好之后,日常基本就是写文章、偶尔升级。前面说的几个点——不用 H2 跑正式站、健康检查等数据库就绪、固定镜像版本、升级前看说明——做到了,后面会省心很多。

个人博客和小型内容站运行 Halo,轻量应用服务器的规格足以承载 Java 应用与数据库同机部署,套餐式计费清晰,配合快照可以在每次升级前保留一份可回退的环境。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、Halo 适合什么场景
  • 二、资源规划与数据库选择
  • 三、部署 Halo
  • 四、配置反向代理与 HTTPS
  • 五、初始化与基础设置
  • 六、主题与插件:先确认版本兼容
  • 七、把附件放到对象存储
  • 八、上线前验证
  • 九、常见故障
  • 十、升级与备份
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档