本手册旨在帮助管理员理解并快速部署基于 Docker Compose 的 Halo 博客系统。该配置针对 24G 内存服务器 进行了性能优化,并采用了环境变量解耦的安全策略。
🏗️ 1. 核心架构说明
该配置采用典型的 App-DB(应用 - 数据库)分层架构:
Halo 容器 (
halo_app):博客主程序,处理业务逻辑、渲染网页。PostgreSQL 容器 (
halo_db_server):关系型数据库,存储文章内容、设置、用户信息。虚拟网桥 (
halo_internal_net):创建一个受保护的局域网,使两个容器可以通过名称(如halodb)互相访问,而不受外部网络干扰。

🛠️ 2. 环境准备(部署前必做)
在宝塔面板或 SSH 终端执行以下步骤,确保基础环境就绪:
① 创建目录并授权
由于 Docker 以 root 权限运行,但内部程序(如 Postgres)有特定的用户 UID,建议预先创建目录并开放读写权限:
# 创建存储数据的根目录
mkdir -p /www/wwwroot/halo/data /www/wwwroot/halo/db
# 赋予最高权限以防止数据库启动失败 (Permission Denied)
chmod -R 777 /www/wwwroot/halo/② 防火墙放行
在宝塔【安全】或云服务器【安全组】中开放以下端口:
8090:博客访问入口。
5432:数据库管理入口(若不需要远程连接数据库,可不开放)。
⚙️ 3. 关键配置项深度解析
🔋 性能调优:JVM 内存
- JVM_OPTS=-Xmx2048m -Xms512mXmx (最大堆内存):2G。在 24G 内存的服务器上,这能确保博客在高并发、处理大量图片插件时依然丝滑,且不会造成系统内存拥堵。
Xms (初始内存):512M。启动时即分配,减少初始运行时的内存申请开销。
🛡️ 自愈机制:健康检查 (Healthcheck)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8090/..."]
start_period: 60s逻辑:Docker 每 30 秒“问”一次 Halo 是否活着。
start_period:因为 Java 程序(Spring Boot)冷启动较慢,如果前 60 秒内报错,Docker 会忽略,不会误以为程序崩溃而不断重启。
🌐 域名依赖:External URL
- HALO_EXTERNAL_URL=http://localhost:8090/重要性:这是小白最容易出错的地方。Halo 后台登录需要校验这个地址。如果你绑定了域名(如
https://blog.com),请务必在此处同步修改。
🚀 4. 部署与维护手册
启动命令
在 /www/wwwroot/halo 目录下运行:
docker-compose up -d状态检查
# 查看容器是否都在运行
docker ps
# 实时查看启动日志(排查报错神器)
docker logs -f halo如何修改数据库密码?
停止容器:
docker-compose down修改 YAML 中 两个服务 的密码项(必须保持一致)。
注意:如果数据库已经初始化,直接改配置可能无效,建议在首次部署前就确定好强密码。
❓ 5. 常见问题 (FAQ)
Q: 为什么状态显示 Starting 或 Unhealthy?
A: Java 应用启动通常需要 30-60 秒。请使用 docker logs -f halo 查看日志。如果一直卡住,请检查是否为 /www/wwwroot/halo/db 权限不足导致数据库崩溃。
Q: 我可以用 Navicat 连接数据库吗?
A: 可以。使用服务器公网 IP,端口 5432,用户名 halo,密码使用你在配置中设置的值。
Q: 如何更新 Halo 版本?
A: 修改 image 标签中的版本号(如 2.24.1 改为 2.25.0),然后重新运行 docker-compose up -d,Docker 会自动拉取新镜像并平滑更新。如果要保持2.x 最新版,版本号改为2即可。
🌰 6. 完整版配置示例
# ==============================================================================
# 🚀 HALO 2.X 博客系统 - 自动化部署母版 (2026 生产级标准)
# ==============================================================================
# 💡 使用说明:
# 1. 本文件已移除所有隐私(路径、密码、IP),直接复制即可安全分享。
# 2. 采用了 ${变量:-默认值} 格式,即使不配置外部变量也能按默认路径运行。
# 3. 适配宝塔面板、大内存服务器(如 Oracle Cloud 24G 实例)。
# ==============================================================================
services:
# ----------------------------------------------------------------------------
# [模块 A] Halo 博客主程序
# ----------------------------------------------------------------------------
halo:
# 镜像地址:官方推荐的稳定版,建议锁定版本号以防自动更新导致数据不兼容
image: registry.fit2cloud.com/halo/halo:2.24.1
container_name: halo_app
restart: always # 策略:服务器重启或程序崩溃时,自动尝试无限次重启
# 启动顺序:必须等下方的 [halodb] 数据库通过健康检查后,博客程序才开始引导
depends_on:
halodb:
condition: service_healthy
networks:
- halo_internal_net # 网络:加入内部隔离网络,不与外部无关容器混用
volumes:
# 【持久化挂载】:[服务器实际路径] : [容器内部路径]
# 作用:把你上传的图片、安装的主题、插件存放在服务器硬盘上,容器删了数据还在
- ${BASE_PATH:-/www/wwwroot/halo}/data:/root/.halo2
ports:
# 【端口映射】:[服务器对外端口] : [容器内部端口]
# 作用:让你通过 http://IP:8090 能够访问到博客
- "${WEB_PORT:-8090}:8090"
healthcheck:
# 【自愈检查】:每 30 秒探测一次后台接口,确保 Java 程序没有假死
test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
interval: 30s # 检查频率
timeout: 5s # 响应超时
retries: 5 # 连续失败 5 次则标记为“不健康”并尝试重启
start_period: 60s # 启动缓冲:Java 启动较慢,前 1 分钟不进行强制判定
environment:
# 【JVM 调优】:针对 24G 内存机器,分配 2G 运行内存给博客,保证极致流畅
- JVM_OPTS=-Xmx2048m -Xms512m
# --- 数据库底层连接环境变量 (强制覆盖模式,比 command 更稳) ---
# 格式:协议://数据库容器名:端口/数据库名
- SPRING_R2DBC_URL=r2dbc:pool:postgresql://halodb:5432/${DB_NAME:-halo_db}
- SPRING_R2DBC_USERNAME=${DB_USER:-halo_user}
- SPRING_R2DBC_PASSWORD=${DB_PASS:-your_strong_password} # 【脱敏:此处填写你的数据库密码】
- SPRING_SQL_INIT_PLATFORM=postgresql
# 【访问域名】:请在此处填写你的真实访问地址(带 http/https),否则后台无法正常登录
- HALO_EXTERNAL_URL=${SITE_URL:-http://localhost:8090/}
# 💡 关键:清空默认指令,防止干扰上述 SPRING 环境变量的生效
command: []
# ----------------------------------------------------------------------------
# [模块 B] PostgreSQL 数据库引擎
# ----------------------------------------------------------------------------
halodb:
# 镜像地址:使用 alpine 版,不仅体积小(仅约 1/4),且安全性更高
image: postgres:15-alpine
container_name: halo_db_server
restart: always
networks:
- halo_internal_net # 数据库仅在内部网桥运行,确保公网无法通过容器名攻击
volumes:
# 【持久化挂载】:存储所有的文章文字、用户信息、设置项
- ${BASE_PATH:-/www/wwwroot/halo}/db:/var/lib/postgresql/data
ports:
# 【数据库映射】:方便你用 Navicat 或 DBeaver 在电脑本地远程管理数据库
# 💡 安全建议:如果不需要远程连接,可以将这一行删掉或在防火墙限制 IP
- "${DB_PORT:-5432}:5432"
healthcheck:
# 【就绪判定】:使用官方工具 pg_isready 确保数据库不仅在运行,且可以接受新连接
test: [ "CMD-SHELL", "pg_isready -U ${DB_USER:-halo_user} -d ${DB_NAME:-halo_db}" ]
interval: 10s
timeout: 5s
retries: 5
environment:
# 数据库初始化参数:这些参数必须与上面 [halo] 模块中的配置一一对应
- POSTGRES_PASSWORD=${DB_PASS:-your_strong_password} # 数据库超级密钥
- POSTGRES_USER=${DB_USER:-halo_user} # 数据库登录用户名
- POSTGRES_DB=${DB_NAME:-halo_db} # 默认创建的数据库库名
- PGUSER=${DB_USER:-halo_user} # 指定健康检查所用的用户
# ------------------------------------------------------------------------------
# [模块 C] 网络隔离定义
# ------------------------------------------------------------------------------
networks:
# 创建一个名为 halo_internal_net 的独立虚拟局域网
halo_internal_net:
driver: bridge # 驱动:桥接模式,提供容器间 DNS 自动发现功能
2026 生产级指南:Halo 2.x + PostgreSQL 自动化部署与性能优化手册
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
赞赏支持
如果觉得文章对你有帮助,可以请作者喝杯咖啡 ☕
评论交流
欢迎留下你的想法