Halo 2.27.1 Docker Compose 部署指南
Halo 2.27.1 Docker Compose 部署指南:显式项目名 halo-2.27.1-stack、Halo + PostgreSQL 17 + Nginx 反代三服务编排,含端口/网段规划、持久化验证、等价 docker run、运维命令与项目名规范化实测。
Halo 2.27.1 Docker Compose 部署指南
目标:用 Docker Compose 在一台 Linux 主机上编排 Halo 2.27.1 + PostgreSQL 17 + Nginx 反向代理,显式固定项目名,规划独立网段与不冲突端口,验证初始化、反向代理与数据持久化。全文命令与回显于 2026-10-27 实测。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- Docker Engine:29.x(Compose v2 插件)
- 项目目录:
~/halo(本文实测路径/opt/data/quzuo/tmp/halo/compose) - Compose 项目名:
halo-2.27.1-stack(声明值),实际生效halo-2271-stack - 应用镜像:
halohub/halo:2.27.1 - 数据库镜像:
postgres:17-alpine - 反向代理镜像:
nginx:1.27-alpine - 宿主端口:Halo
8131、Nginx8132 - 容器网段:
10.89.62.0/24 - 数据目录:
./halo2(挂到/root/.halo2)、./pgdata - 站点地址:
http://127.0.0.1:8131(直连)、http://127.0.0.1:8132(经 Nginx) - 管理账号(示例):
root/q1w2e3r4
⚠️ 网络说明:本次实测环境无法直连 Docker Hub(
docker pull halohub/halo:2.27.1长时间无进展,busybox同样失败),因此用官方halo-2.27.1.jar+ Temurin JDK 21 在本地构建了与官方镜像等价的halohub/halo:2.27.1(同一 JAR、同一启动方式、同样支持JVM_OPTS)。编排、网络、持久化、反代等行为与官方镜像一致;若你的环境可正常拉取,直接使用官方镜像即可,无需自行构建。
二、镜像选型说明
| 镜像 | 用途 | 说明 |
|---|---|---|
halohub/halo:2.27.1 | 应用 | 社区版官方镜像,版本号与 JAR 对齐;2.27、2 为滚动标签,生产建议固定补丁版 |
postgres:17-alpine | 数据库 | 官方 PostgreSQL 17 Alpine 变体,体积小;也可换 mysql:8.4 / mariadb:11 |
nginx:1.27-alpine | 反向代理 | 仅做 80 端口转发与上传体积放宽,可选 |
选择要点:
- Halo 镜像必须与 JAR 版本一致,混用版本会在升级数据结构时出问题。
- 数据库用
alpine变体可减少拉取体积;国内网络可配置镜像加速器。 - Nginx 不是必需组件。若已有宿主机 Nginx 或云负载均衡,可删掉该服务,仅保留 Halo + 数据库。
三、前置条件
docker --version
docker compose version
ss -lntp | grep -E "8131|8132" || echo "端口空闲"
实测回显:
Docker version 29.8.1, build 8bd1a7b
Docker Compose version v2.40.3
端口空闲
端口规划遵循「不占用宿主既有服务」原则:本文选 8131(Halo)与 8132(Nginx),均落在 8128–8152 区间内且未被占用。网段选 10.89.62.0/24,需确认不与宿主已有网段冲突:
docker network ls --format '{{.Name}}' | while read n; do
docker network inspect "$n" --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}}'
done | grep 10.89
实测回显(节选,已存在网段不含 62):
bridge 172.17.0.0/16
dittofeed-v0.24.0-alpha.21-net 10.89.59.0/24
fossil-70 10.89.70.0/24
gitbucket-b1-net 10.89.58.0/24
hoppscotch-v2026-9-stack_hoppscotch-net 10.89.56.0/24
四、部署步骤
4.1 创建项目目录
mkdir -p ~/halo/nginx/conf.d
cd ~/halo
目录约定:halo2/ 存 Halo 工作目录,pgdata/ 存数据库文件,nginx/conf.d/ 存反代配置。三者都要纳入备份。
4.2 编写 docker-compose.yaml
name: halo-2.27.1-stack
services:
halo:
image: halohub/halo:2.27.1
container_name: halo-2.27.1-stack-halo
restart: on-failure:3
depends_on:
halodb:
condition: service_healthy
networks:
- halo-net
volumes:
- ./halo2:/root/.halo2
ports:
- "8131:8090"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
interval: 30s
timeout: 5s
retries: 5
start_period: 60s
environment:
- JVM_OPTS=-Xms256m -Xmx512m
command:
- --spring.r2dbc.url=r2dbc:pool:postgresql://halodb:5432/halo
- --spring.r2dbc.username=halo
- --spring.r2dbc.password=q1w2e3r4
- --spring.sql.init.platform=postgresql
- --halo.external-url=http://127.0.0.1:8131/
- --server.port=8090
halodb:
image: postgres:17-alpine
container_name: halo-2.27.1-stack-halodb
restart: on-failure:3
networks:
- halo-net
volumes:
- ./pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_USER=halo
- POSTGRES_PASSWORD=q1w2e3r4
- POSTGRES_DB=halo
healthcheck:
test: ["CMD-SHELL", "pg_isready -U halo -d halo"]
interval: 10s
timeout: 5s
retries: 6
start_period: 20s
nginx:
image: nginx:1.27-alpine
container_name: halo-2.27.1-stack-nginx
restart: on-failure:3
depends_on:
halo:
condition: service_started
networks:
- halo-net
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
ports:
- "8132:80"
networks:
halo-net:
driver: bridge
ipam:
config:
- subnet: 10.89.62.0/24
关键项说明:
name::Compose 顶层项目名。必须显式声明,否则默认取目录名(如compose),多项目共存时容易撞名。container_name::显式固定容器名,便于运维;不写则由 Compose 自动拼<项目名>-<服务名>-<序号>。depends_on的condition: service_healthy:等 PostgreSQL 健康检查通过再启动 Halo,避免首次连接失败。JVM_OPTS:注入 JVM 堆上限,官方镜像的入口脚本会把它拼进启动命令。command:里的参数等价于application.yaml的spring/halo段,容器化场景推荐用参数而非挂载配置文件。healthcheck的start_period: 60s:Halo 首次启动含数据库迁移,给足冷启动时间。ipam.subnet:固定网段,避免与公司内网/VPN 网段冲突。
4.3 编写 Nginx 反代配置
nginx/conf.d/halo.conf:
server {
listen 80;
server_name _;
client_max_body_size 1024m;
location / {
proxy_pass http://halo:8090;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
要点:
client_max_body_size 1024m:Halo 默认不限制上传大小,反代默认只有 1 MB,不放开会导致大附件 413。X-Forwarded-Proto:Halo 据此判断原始协议,HTTPS 终止在 Nginx 时必须带。Upgrade/Connection:插件或后台的 WebSocket 长连接需要。
4.4 启动
docker compose up -d
实测回显:
Network halo-2271-stack_halo-net Creating
Network halo-2271-stack_halo-net Created
Container halo-2.27.1-stack-halodb Creating
Container halo-2.27.1-stack-halodb Created
Container halo-2.27.1-stack-halo Creating
Container halo-2.27.1-stack-halo Created
Container halo-2.27.1-stack-nginx Creating
Container halo-2.27.1-stack-nginx Created
Container halo-2.27.1-stack-halodb Starting
Container halo-2.27.1-stack-halodb Started
Container halo-2.27.1-stack-halodb Waiting
Container halo-2.27.1-stack-halodb Healthy
Container halo-2.27.1-stack-halo Starting
Container halo-2.27.1-stack-halo Started
Container halo-2.27.1-stack-nginx Starting
Container halo-2.27.1-stack-nginx Started
⚠️ 注意:声明的是
halo-2.27.1-stack,实际创建的网络叫halo-2271-stack_halo-net。Compose 会把项目名规范化为「小写字母、数字、连字符、下划线」,点号被移除,因此2.27.1变成2271。用docker network ls或docker compose ls核对时要以规范化后的名字为准:halo-2271-stack running(3) /opt/data/quzuo/tmp/halo/compose/docker-compose.yaml
docker compose config里也会显示name: halo-2271-stack。
4.5 验证运行状态
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
halo-2.27.1-stack-halo halohub/halo:2.27.1 "/entrypoint.sh --sp…" halo 7 seconds ago Up (healthy) 0.0.0.0:8131->8090/tcp, [::]:8131->8090/tcp
halo-2.27.1-stack-halodb postgres:17-alpine "docker-entrypoint.s…" halodb 7 seconds ago Up 6 seconds (healthy) 5432/tcp
halo-2.27.1-stack-nginx nginx:1.27-alpine "/docker-entrypoint.…" nginx 7 seconds ago Up 0.0.0.0:8132->80/tcp, [::]:8132->80/tcp
启动日志:
docker logs halo-2.27.1-stack-halo 2>&1 | grep -E "Version:|Netty started|Started Application"
实测回显:
Version: 2.27.1
2026-10-27T13:38:02.683Z INFO 1 --- [ main] o.s.boot.reactor.netty.NettyWebServer : Netty started on port 8090 (http)
2026-10-27T13:38:02.870Z INFO 1 --- [ main] run.halo.app.Application : Started Application in 12.685 seconds (process running for 13.646)
容器化启动比裸机 JAR 稍慢(12.7 秒 vs 7.2 秒),主要耗时在数据库迁移与健康检查等待。
验证网络与 IP 分配:
docker network inspect halo-2271-stack_halo-net \
--format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}}{{end}} {{range .Containers}}{{.Name}}={{.IPv4Address}} {{end}}'
实测回显:
halo-2271-stack_halo-net 10.89.62.0/24 halo-2.27.1-stack-halodb=10.89.62.2/24 halo-2.27.1-stack-nginx=10.89.62.4/24 halo-2.27.1-stack-halo=10.89.62.3/24
Halo 通过服务名 halodb 访问数据库,无需知道 IP;IP 由 Compose 按网段顺序分配。
4.6 初始化站点
浏览器访问 http://<服务器IP>:8131/console,填写站点信息:
- 站点标题:
Halo Compose 站点 - 管理员:
root/q1w2e3r4 - 邮箱:
root@quzuo.net - 外部访问地址:
http://<服务器IP>:8131 - 语言:简体中文
初始化后验证直连与反代:
curl -s -o /dev/null -w "halo8131=%{http_code}\n" http://127.0.0.1:8131/
curl -s -o /dev/null -w "nginx8132=%{http_code}\n" http://127.0.0.1:8132/
curl -s http://127.0.0.1:8132/ | grep -o "<title>[^<]*</title>"
实测回显:
halo8131=200
nginx8132=200
<title>Halo Compose 站点</title>
五、数据持久化说明
Halo 的所有状态分两处存放:
./halo2→ 容器内/root/.halo2:附件、主题、插件、索引、日志、PAT 密钥(数据库内容不在这里)。./pgdata→ 容器内/var/lib/postgresql/data:站点内容、用户、配置全部在 PostgreSQL 的extensions表中。
实测目录体积:
du -sh halo2 pgdata
ls halo2
26M halo2
47M pgdata
backups
indices
keys
logs
plugins
themes
停机再启动验证数据不丢:
docker compose down
docker compose up -d
sleep 40
docker compose ps
curl -s -o /dev/null -w "home_after_down_up=%{http_code}\n" http://127.0.0.1:8131/
实测回显:
NAME STATUS PORTS
halo-2.27.1-stack-halo Up 40 seconds (healthy) 0.0.0.0:8131->8090/tcp, [::]:8131->8090/tcp
halo-2.27.1-stack-halodb Up 46 seconds (healthy) 5432/tcp
halo-2.27.1-stack-nginx Up 40 seconds 0.0.0.0:8132->80/tcp, [::]:8132->80/tcp
home_after_down_up=200
⚠️ 注意:
docker compose down默认保留命名卷与绑定目录,数据不会丢;但docker compose down -v会删除命名卷。本项目全部用绑定挂载(./halo2、./pgdata),所以-v对它们无效,真正的风险是手工rm -rf pgdata。
💡 说明:备份要「目录 + 数据库」一起做。只备份
halo2会丢掉全部文章;只pg_dump会丢掉附件与主题包。推荐停机备份或数据库在线pg_dump+ 目录rsync。
六、环境变量表
| 变量 | 作用域 | 示例值 | 说明 |
|---|---|---|---|
JVM_OPTS | halo | -Xms256m -Xmx512m | 注入 JVM 堆参数;置空表示不追加 |
POSTGRES_USER | halodb | halo | 初始化时创建的超级用户 |
POSTGRES_PASSWORD | halodb | q1w2e3r4 | 数据库密码,示例值;生产用强口令并改用 secrets |
POSTGRES_DB | halodb | halo | 初始数据库名,必须与 Halo 的 URL 一致 |
确认 JVM 参数已生效:
docker exec halo-2.27.1-stack-halo ps -ef | grep [j]ava
实测回显:
root 1 0 77 13:39 ? 00:00:32 /opt/java/bin/java -Dfile.encoding=UTF-8 -Xms256m -Xmx512m -jar /application/halo.jar --spring.r2dbc.url=r2dbc:pool:postgresql://halodb:5432/halo --spring.r2dbc.username=halo --spring.r2dbc.password=q1w2e3r4 --spring.sql.init.platform=postgresql --halo.external-url=http://127.0.0.1:8131/ --server.port=8090
七、配置参数说明
Compose 场景下 Halo 的配置通过 command: 数组传入,等价于命令行参数:
| 参数 | 本文取值 | 说明 |
|---|---|---|
spring.r2dbc.url | r2dbc:pool:postgresql://halodb:5432/halo | 主机名用 Compose 服务名 halodb,不要写 localhost |
spring.r2dbc.username | halo | 与 POSTGRES_USER 一致 |
spring.r2dbc.password | q1w2e3r4 | 与 POSTGRES_PASSWORD 一致 |
spring.sql.init.platform | postgresql | 必须是 postgresql/mysql/mariadb/h2 之一 |
halo.external-url | http://127.0.0.1:8131/ | 对外地址,影响邮件链接与永久链接 |
server.port | 8090 | 容器内端口,与 ports 的右侧一致 |
💡 说明:
--spring.r2dbc.url里写localhost是最常见的错误——容器内的localhost是 Halo 自己,连不到数据库。必须用 Compose 服务名(同一自定义网络内由内置 DNS 解析)。
八、配置文件挂载
如果不想把参数堆在 command 里,可改为挂载 application.yaml:
volumes:
- ./halo2:/root/.halo2
# ./halo2/application.yaml
server:
port: 8090
spring:
r2dbc:
url: r2dbc:pool:postgresql://halodb:5432/halo
username: halo
password: q1w2e3r4
sql:
init:
mode: always
platform: postgresql
halo:
work-dir: /root/.halo2
external-url: http://127.0.0.1:8131
Halo 默认会读取工作目录下的 application.yaml(官方镜像以 /root/.halo2 为工作目录),无需额外加 --spring.config.additional-location。同一项配置「命令行参数」优先级高于配置文件,两者并存时以 command 为准。
九、等价 docker run
不使用 Compose 时,单容器等价命令如下(实测在 8133 端口跑通):
docker network create --subnet 10.89.62.0/24 halo-net
docker run -d --name halo-2271-run \
--network halo-net \
-p 8133:8090 \
-e "JVM_OPTS=-Xms256m -Xmx512m" \
-v ~/halo/halo2:/root/.halo2 \
halohub/halo:2.27.1 \
--spring.r2dbc.url=r2dbc:pool:postgresql://halodb:5432/halo \
--spring.r2dbc.username=halo \
--spring.r2dbc.password=q1w2e3r4 \
--spring.sql.init.platform=postgresql \
--halo.external-url=http://127.0.0.1:8133/ \
--server.port=8090
实测验证:
halo-2271-run-check Up 35 seconds
run8133=302
302 表示控制台已就绪并跳转登录页。注意该命令依赖已存在的 halodb 容器与 halo-net 网络,单独执行前需先按第四章启动数据库服务。
十、常用运维命令
cd ~/halo
docker compose ps # 查看状态
docker compose logs -f halo # 跟踪应用日志
docker compose restart halo # 只重启应用
docker compose stop # 停止全部
docker compose down # 停止并删除容器与网络(保留绑定目录)
docker compose pull && docker compose up -d # 升级镜像
升级前先备份:
docker exec halo-2.27.1-stack-halodb pg_dump -U halo halo > halo-$(date +%F).sql
tar czf halo2-$(date +%F).tar.gz halo2
实测 pg_dump 输出(节选):
--
-- PostgreSQL database dump
--
-- Dumped from database version 17.6
十一、常见问题
11.1 项目名与我写的不一致
halo-2.27.1-stack 被规范化为 halo-2271-stack,点号被移除。查看实际项目名:
docker compose ls
docker network ls | grep halo
11.2 拉取镜像超时 / 卡在 Pulling
docker pull halohub/halo:2.27.1
实测在受限网络下长时间无进展。处理办法:配置镜像加速器,或在可联网机器上 docker save 后 docker load;也可用官方 JAR 自建同版本镜像(本文实测即为此方案)。
11.3 Halo 启动即退出,日志提示连不上数据库
docker compose logs halo | grep -i "connection\|refused" | head
排查顺序:halodb 是否 healthy、URL 主机名是否写成 localhost、密码是否与 POSTGRES_PASSWORD 一致。
docker exec halo-2.27.1-stack-halodb pg_isready -U halo -d halo
实测回显:
/var/run/postgresql:5432 - accepting connections
11.4 Nginx 返回 502
proxy_pass http://halo:8090 依赖同一网络内的服务名解析。确认 nginx 与 halo 在同一网络:
docker inspect halo-2.27.1-stack-nginx \
--format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}}{{end}}'
实测回显:
halo-2271-stack_halo-net
11.5 上传附件 413
Nginx 默认 client_max_body_size 1m。在 halo.conf 的 server 块加大后 reload:
docker exec halo-2.27.1-stack-nginx nginx -t
docker exec halo-2.27.1-stack-nginx nginx -s reload
实测回显:
nginx: configuration file /etc/nginx/nginx.conf test is successful
十二、参考链接
- Halo 官方文档:https://docs.halo.run
- 使用 Docker Compose 部署:https://docs.halo.run/guide/install/docker-compose
- 配置说明:https://docs.halo.run/guide/install/config
- 2.27.1 发布说明:https://github.com/halo-dev/halo/releases/tag/v2.27.1
- Docker Compose 文件规范:https://docs.docker.com/compose/compose-file/