本文属于「自托管 Docker 部署实战」系列(共 35 篇),第 8 篇。 示例中的 IP(192.0.2.10)、域名(example.com)、密码均为占位符,请按实际环境替换。

它是什么

Halo 是 Java 写的开源建站工具,插件生态和主题都比较成熟。halo-pro 是商业版镜像(需要授权 Key),社区版用 halohub/halo。

前置条件

  • 一台 Linux 服务器(1C1G 起步;Java 类应用建议 2C4G 以上);
  • 已安装 Docker 与 Compose v2,执行 docker compose version 有版本号输出;
  • 所有示例里的 IP / 域名 / 密码都是占位符,实际部署请替换成自己的。
# 安装 Docker(已安装可跳过)
curl -fsSL https://get.docker.com | sh

# 目录约定:一个服务一个目录,后文的 ./data 均指栈目录内
mkdir -p /srv/docker/active/<stack> && cd /srv/docker/active/<stack>

镜像地址

halohub/halo-pro:2.27.0
mysql:8.4.7

目录结构

/srv/docker/active/halo/
├── docker-compose.yml
├── .env
├── data/                 # Halo 工作目录(附件、主题、插件)
└── mysql-data/           # 如果 MySQL 也放同一目录

部署步骤

# docker-compose.yml
services:
  halo:
    image: halohub/halo-pro:2.27.0
    container_name: halo
    restart: always
    depends_on:
      mysql:
        condition: service_healthy
    command:
      - --spring.r2dbc.url=r2dbc:pool:mysql://mysql:3306/halo
      - --spring.r2dbc.username=halo
      - --spring.r2dbc.password=${HALO_DB_PASSWORD}
      - --spring.sql.init.platform=mysql
      - --halo.external-url=https://blog.example.com
    ports:
      - "8090:8090"
    volumes:
      - ./data:/root/.halo2
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s

  mysql:
    image: mysql:8.4.7
    container_name: halo-mysql
    restart: always
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=halo
      - MYSQL_USER=halo
      - MYSQL_PASSWORD=${HALO_DB_PASSWORD}
      - TZ=Asia/Shanghai
    volumes:
      - ./mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
      interval: 10s
      timeout: 5s
      retries: 10
docker compose up -d
docker compose logs -f halo

打开 http://<SERVER_IP>:8090 完成初始化,再配置域名和 HTTPS。

关键配置

  • --halo.external-url 必须写最终对外地址(含协议),否则后台生成的链接、邮件、OAuth 回调全错;
  • 数据库连接串用 mysql 服务名,不要写 127.0.0.1(容器内的 localhost 是容器自己);
  • 数据目录是 /root/.halo2,附件多的话注意磁盘;
  • 生产环境前面套一层 Nginx/OpenResty 做 TLS 和缓存。

注意事项

  • Halo Pro 需要授权,没买授权会限制部分能力,个人博客用社区版即可;
  • 升级前备份 data/ 和数据库,Halo 大版本升级有数据库迁移;
  • 主题/插件装多了会拖慢启动,JVM_OPTS 可按内存调整(4G 内存给 -Xmx1g 左右);
  • 若用 1Panel 安装,面板会生成 .env 注入数据库参数,不要手改 compose 里的 ${},去面板改。

备份与升级

# 1) 数据库逻辑备份
docker exec halo-mysql sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --single-transaction --all-databases' | gzip > "halo-db-$(date +%F).sql.gz"

# 2) 站点数据(附件/主题/插件)
tar czf "halo-data-$(date +%F).tar.gz" ./data

# 3) 升级
docker compose pull
docker compose up -d
  • 大版本升级会做数据库迁移,必须先备份;
  • Halo Pro 的授权与版本绑定,升级后若提示授权异常,回滚旧 tag。