雷池 WAF 一键升级失败解决:手动离线升级注意事项

Blog

背景

雷池(SafeLine)近期版本更新到了 9.4.0(2026-08-17 发布),更新和优化了大量的检测逻辑,所以打算更新雷池。

但按照官方教程执行一键升级失败,提示”未安装 Docker Compose,是否自动安装”,迷迷糊糊选择”是”之后就显示更新失败,并且服务中断了半小时。

最终我选择了离线镜像升级方案。

本文记录了升级过程中遇到的几个典型错误及完整的排查解决过程,希望能为遇到类似问题的朋友提供参考。

升级环境

项目配置
操作系统Ubuntu 22.04 / 24.04
Docker已安装
Docker Compose独立二进制 docker-compose(非 docker compose 插件)
雷池安装目录/data/safeline

为何在线升级会失败?

版本要求明确,但文档指引存在歧义。 雷池官方手动安装文档没有明确指明 Docker Compose 的版本要求,示例命令清一色是 docker compose up -d(无横线,v2 插件形式)。但我就要用 docker-compose(带横线,v1 独立二进制)—— 你又没说不可以 QaQ。

docker compose 与 docker-compose 是两种不同的工具:

  • docker compose:随新版 Docker 一起安装的插件,官方主推的现代版本。
  • docker-compose:需要单独下载的独立二进制文件,但我爱用咋地 QaQ。

脚本检测机制存在 Bug(缺陷好吧只是缺陷)。 雷池的在线升级脚本(manager.py)在检测 Compose 版本时,用了一条只匹配 v2 输出格式的正则,导致 v1 用户被误判为”未安装 Compose”,进而触发”是否自动安装 Docker”的询问。迷迷糊糊选了”是”之后,脚本执行 get-docker.sh 并在末尾 systemctl restart docker 硬重启 Docker daemon,所有运行中的容器瞬间被杀 —— 服务中断。

根因深挖:manager.py 的正则缺陷(选读)

bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release/latest/manager.sh)" 中真正的升级逻辑代码 manager.py 的 precheck_docker_compose() 函数用以下正则提取 Compose 版本号:

t = re.findall(r'^Docker Compose version v?(\d+)\.', version_output)

这条正则只匹配 v2 的输出格式 Docker Compose version v2.x.x,完全不匹配 v1 的输出格式 docker-compose version 1.29.2(小写、带横线、无 v 前缀)。

脚本逻辑是:如果正则匹配结果为空,就判定”Compose 未安装”,然后弹出”是否自动安装 Docker”的询问。用户一旦选”是”,install_docker() 就会执行 get-docker.sh,并在末尾通过 start_docker() 调用:

systemctl enable docker && systemctl daemon-reload && systemctl restart docker

systemctl restart docker 会硬重启 Docker daemon,所有运行中的容器被强制停止。如果 get-docker.sh 安装过程中出现网络超时或依赖冲突,Docker 服务可能起不来,所有容器全部下线 —— 这就是服务中断的真正原因。

简而言之:不是你的 docker-compose 有问题,是脚本的正则不认你的 docker-compose。

问题已经在文章发布前 提交雷池官方

官方离线升级步骤

根据雷池官方文档,离线升级需要执行以下操作:

# 1. 进入安装目录
cd /data/safeline

# 2. 备份旧编排文件,下载新版
mv compose.yaml compose.yaml.old
wget "https://waf-ce.chaitin.cn/release/latest/compose.yaml" --no-check-certificate -O compose.yaml

# 3. 更新/补全 .env 环境变量
sed -i "s/IMAGE_TAG=.*/IMAGE_TAG=latest/g" ".env"
grep "SAFELINE_DIR" ".env" > /dev/null || echo "SAFELINE_DIR=$(pwd)" >> ".env"
grep "IMAGE_TAG" ".env" > /dev/null || echo "IMAGE_TAG=latest" >> ".env"
grep "MGT_PORT" ".env" > /dev/null || echo "MGT_PORT=9443" >> ".env"
grep "POSTGRES_PASSWORD" ".env" > /dev/null || echo "POSTGRES_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32)" >> ".env"
grep "SUBNET_PREFIX" ".env" > /dev/null || echo "SUBNET_PREFIX=172.22.222" >> ".env"
grep "IMAGE_PREFIX" ".env" >/dev/null || echo "IMAGE_PREFIX=chaitin" >>".env"
grep "ARCH_SUFFIX" ".env" >/dev/null || echo "ARCH_SUFFIX=" >>".env"
grep "RELEASE" ".env" >/dev/null || echo "RELEASE=" >>".env"
grep "MGT_PROXY" ".env" >/dev/null || echo "MGT_PROXY=0" >>".env"

# 4. 加载离线镜像
docker load -i image.tar.gz

# 5. 停止旧容器并启动新容器
docker compose down --remove-orphans
docker compose up -d

遇到的错误及解决方案

错误现象根因解决方案
docker compose 命令不存在系统装的是 v1 独立二进制,v2 插件未安装统一改用 docker-compose(带横线)
网络删除失败(active endpoints)其他容器(如 WordPress)连接到 safeline-ce 网络忽略或手动断开
invalid reference formatcompose.yaml 中 postgres 镜像引用语法错误手动修正 image 字段
镜像前缀不匹配.env 中 IMAGE_PREFIX 指向华为云,本地标签是 chaitin改为 IMAGE_PREFIX=chaitin

错误一:docker compose 命令不存在

现象: 执行 docker compose down --remove-orphans 时报错:

docker: 'compose' is not a docker command.
See 'docker --help'

定位过程: 检查环境中的 Docker Compose 版本:

which docker-compose
# 输出:/usr/bin/docker-compose

docker-compose --version
# 输出:docker-compose version 1.29.2

原因: 系统中安装的是独立二进制 docker-compose(带横线,v1),而非新版 docker compose 插件(无横线、子命令形式,v2)。v1 的 1.29.2 实际是支持 --remove-orphans 这个 flag 的,真正不存在的不是参数,而是 docker compose(无横线)这个子命令本身。

解决方案: 所有命令统一使用 docker-compose(带横线):

docker-compose down --remove-orphans
docker-compose up -d

错误二:docker-compose down 网络删除失败

现象:

Removing network safeline-ce
ERROR: error while removing network: network safeline-ce has active endpoints (name:"wordpress" id:"a5710bbfdfb6")

原因: 服务器上存在其他容器(如 WordPress)连接到雷池创建的 safeline-ce 网络,导致网络无法删除。

影响: 此错误不影响升级。网络仍然存在,新启动的容器会直接复用该网络。

解决方案: 忽略该错误,继续执行 docker-compose up -d。若希望彻底清理,可先断开其他容器的网络连接:

docker network disconnect safeline-ce wordpress
docker network rm safeline-ce

错误三:invalid reference format(核心问题)

现象: 执行 docker-compose up -d 反复报错:

ERROR: invalid reference format

定位过程: 使用 docker-compose config 命令检查 Compose 解析后的实际配置:

docker-compose config

在输出中发现 postgres 服务的 image 字段异常:

postgres:
  image: $${IMAGE_PREFIX/safeline-postgres:15.18}

这是一个语法错误 —— 多了一个 $,且变量引用格式不正确(} 位置错位,把斜杠后面的内容也包进了变量名里)。其他服务的 image 字段均正常(如 chaitin/safeline-chaos:latest),唯独 postgres 服务异常。

原因: 新下载的 compose.yaml 中 postgres 的 image 行存在拼写错误,将正确的变量格式 ${IMAGE_PREFIX}/safeline-postgres:${IMAGE_TAG} 误写为 $${IMAGE_PREFIX/safeline-postgres:15.18}。在 Compose 中,$$ 是对 $ 的转义,会让变量替换整段失效,最终拼出来的镜像名既不是合法引用,也不是本地存在的标签,于是触发 invalid reference format

解决方案: 手动编辑 compose.yaml,修正 postgres 服务的镜像引用。

vim compose.yaml

找到 postgres: 服务部分,将:

    image: $${IMAGE_PREFIX/safeline-postgres:15.18}

改为(使用本地已加载的镜像标签):

    image: chaitin/safeline-postgres:15.2

保存退出后,再次验证:

docker-compose config | grep -A 2 postgres

确认输出中 image: chaitin/safeline-postgres:15.2

错误四:IMAGE_PREFIX 与本地镜像标签不匹配

现象: 修改 compose.yaml 后,docker-compose up -d 仍然报 invalid reference format

定位过程: 查看本地已加载的镜像标签:

docker images | grep safeline

发现镜像同时带有两套标签:

chaitin/safeline-*:latest
swr.cn-east-3.myhuaweicloud.com/chaitin-safeline/safeline-*:latest

而 .env 中初始配置为:

IMAGE_PREFIX=swr.cn-east-3.myhuaweicloud.com/chaitin-safeline

原因: compose.yaml 中其他服务使用 ${IMAGE_PREFIX}/safeline-*:${IMAGE_TAG} 引用镜像。当 IMAGE_PREFIX 指向华为云地址时,Compose 尝试使用华为云标签的镜像。虽然本地也有这些标签,但若标签不完全匹配,可能导致解析异常。

解决方案: 将 IMAGE_PREFIX 改为 chaitin,使用本地已有的简洁标签:

sed -i 's/^IMAGE_PREFIX=.*/IMAGE_PREFIX=chaitin/' .env

最终成功启动

完成以上修复后:

docker-compose up -d

输出:

Creating safeline-pg       ... done
Creating safeline-chaos    ... done
Creating safeline-detector ... done
Creating safeline-fvm      ... done
Creating safeline-tengine  ... done
Creating safeline-mgt      ... done
Creating safeline-luigi    ... done

查看容器状态:

docker-compose ps
# 所有服务均为 Up 状态

登录管理页面,版本已更新,配置、规则、日志全部保留。

经验总结

  1. 升级前务必备份/制作服务器镜像: 任何涉及底层组件(如 Docker)更新或使用官方脚本的操作都存在破坏性风险。在执行升级前,务必在云服务商控制台为服务器制作系统盘快照或镜像。这样即使升级彻底失败导致环境崩溃(例如本次脚本硬重启 Docker 导致服务中断),也能通过回滚镜像在几分钟内恢复业务,避免长时间的手忙脚乱。
  2. 确认 Docker Compose 命令格式: 使用 which docker-compose 确认系统中是 docker-compose(v1)还是 docker compose(v2),避免命令混淆。两者语法不同,不要混用。
  3. 善用 docker-compose config 预检查: 这是定位 Compose 配置问题的利器,能提前发现变量解析错误和语法问题。
  4. 检查 compose.yaml 中的语法错误: 官方提供的编排文件也可能存在拼写问题,尤其是 image 字段的变量引用格式。对 ${VAR} 与 $$(转义)的用法要格外敏感。
  5. 确保 .env 中的镜像前缀与本地标签一致: IMAGE_PREFIX 应匹配 docker load 加载的镜像标签前缀。离线升级时,建议统一用 chaitin 简短前缀。
  6. 网络残留错误不影响升级: docker-compose down 网络删除失败时,只要容器已停止,新容器会复用现有网络,不影响启动。
  7. 手动编辑比 sed 更可靠: 在复杂替换场景下,直接使用 vim 修改文件可以避免转义错误。
  8. 别盲目相信安装脚本的”自动安装”选项: 安装脚本若提示要自动安装 Docker,先停下来 —— 它很可能会重启 Docker daemon,把你正在运行的服务全杀掉。先在宿主机上手动把 Docker 和 Compose 准备好,再运行业务安装器。

参考资料

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注