这是经过排错、解决方言冲突和 OOM 内存卡死后,最终调优稳定的完整 docker-compose.yml(位于 /opt/halo/docker-compose.yml):

YAML

services:
  halo-mysql:
    image: mysql:8.0
    container_name: halo-mysql
    restart: unless-stopped
    security_opt:
      - seccomp:unconfined     # 解决 Linux 沙箱拦截 mbind/NUMA 内存调用的警告
    command:
      - --default-authentication-plugin=mysql_native_password
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --innodb-buffer-pool-size=256M  # 内存约束:将缓冲池压至 256MB,防止吃满内存
      - --max-connections=50            # 限制最大连接数,减少每个连接的缓存开销
    environment:
      MYSQL_ROOT_PASSWORD: "HaloUser123456"
      MYSQL_DATABASE: halo
      MYSQL_USER: halo
      MYSQL_PASSWORD: "HaloUser123456"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-p$$MYSQL_ROOT_PASSWORD"]
      interval: 5s
      timeout: 5s
      retries: 30
      start_period: 30s
    volumes:
      - ./mysql-data:/var/lib/mysql     # MySQL 数据持久化卷
    networks:
      - default

  halo:
    image: ghcr.io/halo-dev/halo:2.24.2
    container_name: halo
    restart: unless-stopped
    depends_on:
      halo-mysql:
        condition: service_healthy      # 核心点:必须等 MySQL 健康检查通过后才拉起 Halo
    ports:
      - "8090:8090"
    volumes:
      - ./data:/root/.halo2             # 博客静态资源、主题与附件存储目录
    environment:
      - JVM_OPTS=-Xms256m -Xmx512m      # 内存约束:限制 JVM 初始 256MB,最大堆内存 512MB
      - SPRING_R2DBC_URL=r2dbc:pool:mysql://halo-mysql:3306/halo
      - SPRING_R2DBC_USERNAME=halo
      - SPRING_R2DBC_PASSWORD=HaloUser123456
      - SPRING_SQL_INIT_PLATFORM=mysql  # 核心点:显式锁定方言为 MySQL,避免底层迁移工具语法报错
      - HALO_EXTERNAL_URL=https://originspace.work
    networks:
      - default

networks:
  default:
    name: web-net
    external: true

配套组件:Nginx Proxy Manager(NPM)的 Compose

另外,作为前端接入层的 NPM 则是放在独立目录(如 /opt/npm/docker-compose.yml)下独立编排的:

YAML

version: '3.8'

services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: npm-app-1
    restart: unless-stopped
    ports:
      - '80:80'      # HTTP 访问
      - '81:81'      # NPM 管理后台面板
      - '443:443'    # HTTPS 加密访问
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt  # Certbot 证书存储
    networks:
      - default

networks:
  default:
    name: web-net
    external: true