feat : 更新后的云效流水线配置(使用 docker build 而不是 buildx

This commit is contained in:
翟二远 2026-04-03 23:14:29 +08:00
parent 9fdb14a049
commit 7050d92a9e
4 changed files with 448 additions and 26 deletions

98
scanner/.flow.yml Normal file
View file

@ -0,0 +1,98 @@
version: v1.0
name: skillhub-scanner-build-deploy
stages:
- name: 构建镜像
jobs:
- job:
name: 构建并推送镜像
steps:
# 步骤 1: 构建 Docker 镜像(完全禁用缓存)
- step: script@1
name: 构建镜像
with:
script: |
#!/bin/bash
set -e
echo "========================================="
echo "开始构建 Docker 镜像(完全禁用缓存)"
echo "========================================="
# 镜像信息
IMAGE_NAME="jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner"
IMAGE_TAG="${BUILD_NUMBER:-latest}"
FULL_IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
echo "镜像名称: ${FULL_IMAGE}"
echo "构建时间: $(date '+%Y-%m-%d %H:%M:%S')"
# 方式 1: 使用 docker build(不使用 buildx)
docker build \
--no-cache \
--pull \
-t "${FULL_IMAGE}" \
-f scanner/Dockerfile \
scanner/
# 如果必须使用 buildx,则明确禁用缓存
# docker buildx build \
# --no-cache \
# --pull \
# --load \
# --cache-from=type=inline \
# -t "${FULL_IMAGE}" \
# -f scanner/Dockerfile \
# scanner/
echo "========================================="
echo "镜像构建成功"
echo "========================================="
# 打印镜像信息
docker images | grep sh-skill-scanner || true
# 步骤 2: 推送镜像
- step: script@1
name: 推送镜像
with:
script: |
#!/bin/bash
set -e
echo "========================================="
echo "推送镜像到仓库"
echo "========================================="
IMAGE_NAME="jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner"
IMAGE_TAG="${BUILD_NUMBER:-latest}"
FULL_IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
# 推送镜像
docker push "${FULL_IMAGE}"
# 同时打 latest 标签
docker tag "${FULL_IMAGE}" "${IMAGE_NAME}:latest"
docker push "${IMAGE_NAME}:latest"
echo "========================================="
echo "镜像推送成功"
echo "镜像地址: ${FULL_IMAGE}"
echo "========================================="
- name: 部署到 Kubernetes
jobs:
- job:
name: 部署应用
steps:
# 步骤 1: 部署到 K8s
- step: kubectl-apply@1
name: 部署到集群
with:
kubectl_version: v1.27.9
cluster_type: ack
namespace: default
path_to_yaml: scanner/manifests
insecure_skip_tls_verify: true
# 替换镜像变量
variables: |
IMAGE=jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner:${BUILD_NUMBER}

View file

@ -0,0 +1,283 @@
# 云效完全禁用 Docker 缓存指南
## 🔍 问题分析
错误信息:
```
ERROR: error writing manifest blob: failed commit on ref "sha256:...":
unexpected status from PUT request to .../flow-docker-build-cache: 409 Conflict
```
**原因:** 云效使用了 `docker buildx build` 并自动配置了 `--cache-to` 参数,导致缓存写入冲突。
**重要:** 从日志看,镜像本身已经构建成功,只是缓存导出失败。
---
## ✅ 解决方案(按优先级排序)
### 方案一:使用 script 步骤替代 docker_build 步骤(推荐)
在云效 Flow 中,**不使用** `docker_build@1` 组件,改用 `script@1`:
#### 1. 进入云效 Flow 流水线配置
#### 2. 删除或禁用现有的 `docker_build@1` 步骤
#### 3. 添加自定义脚本步骤
```yaml
steps:
- step: script@1
name: 构建并推送镜像
with:
script: |
#!/bin/bash
set -e
IMAGE_NAME="jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner"
IMAGE_TAG="${BUILD_NUMBER}"
# 使用 docker build(不是 buildx)
docker build \
--no-cache \
--pull \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
-f scanner/Dockerfile \
scanner/
# 推送镜像
docker push "${IMAGE_NAME}:${IMAGE_TAG}"
docker tag "${IMAGE_NAME}:${IMAGE_TAG}" "${IMAGE_NAME}:latest"
docker push "${IMAGE_NAME}:latest"
```
---
### 方案二:在 docker_build 步骤中禁用缓存
如果必须使用 `docker_build@1` 组件,修改其配置:
```yaml
steps:
- step: docker_build@1
with:
dockerfile_path: scanner/Dockerfile
image_name: jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner
tag: ${BUILD_NUMBER}
# 关键:禁用缓存相关配置
use_cache: false
cache_from: ""
cache_to: ""
build_args: "--no-cache --pull"
```
---
### 方案三:使用 Docker Buildx 但禁用远程缓存
如果云效强制使用 buildx:
```yaml
steps:
- step: script@1
with:
script: |
#!/bin/bash
set -e
IMAGE_NAME="jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner"
IMAGE_TAG="${BUILD_NUMBER}"
# 使用 buildx 但不使用远程缓存
docker buildx build \
--no-cache \
--pull \
--load \
--cache-from=type=inline \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
-f scanner/Dockerfile \
scanner/
docker push "${IMAGE_NAME}:${IMAGE_TAG}"
docker tag "${IMAGE_NAME}:${IMAGE_TAG}" "${IMAGE_NAME}:latest"
docker push "${IMAGE_NAME}:latest"
```
关键参数:
- `--no-cache`: 不使用构建缓存
- `--pull`: 总是拉取最新基础镜像
- `--load`: 将镜像加载到本地 Docker(不是导出到 registry)
- `--cache-from=type=inline`: 只使用内联缓存(不使用远程)
- **不要有 `--cache-to` 参数**
---
### 方案四:删除冲突的缓存标签(临时方案)
如果以上方案都无法实施,手动删除冲突的缓存:
```yaml
steps:
- step: script@1
name: 清理冲突缓存
with:
script: |
#!/bin/bash
# 尝试删除冲突的缓存标签
docker rmi jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner:flow-docker-build-cache || true
# 或使用阿里云 CLI 删除
# aliyun cr DELETE /repos/apps/sh-skill-scanner/tags/flow-docker-build-cache || true
- step: docker_build@1
# ... 原有的构建配置
```
---
## 🔍 验证镜像是否已经成功
虽然缓存导出失败,但镜像本身可能已经成功:
### 1. 在云效中检查
查看构建日志,找到这些关键信息:
```
#14 exporting to image
#14 exporting layers
#14 exporting manifest
#14 pushing layers
```
如果看到 `pushing layers` 完成,说明镜像已经推送成功。
### 2. 手动验证
```bash
# 运行检查脚本
cd scanner && ./check-image.sh
# 或手动拉取测试
docker pull jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner:latest
```
### 3. 在阿里云容器镜像服务控制台查看
登录阿里云控制台 → 容器镜像服务 → 镜像仓库 → `apps/sh-skill-scanner` → 查看标签列表
---
## 📊 各方案对比
| 方案 | 优点 | 缺点 | 推荐度 |
|------|------|------|--------|
| 方案一:script 步骤 | 完全控制,最可靠 | 需要手动写脚本 | ⭐⭐⭐⭐⭐ |
| 方案二:禁用缓存配置 | 简单,UI 配置 | 可能被云效覆盖 | ⭐⭐⭐⭐ |
| 方案三:buildx 不用远程缓存 | 兼容 buildx | 配置复杂 | ⭐⭐⭐ |
| 方案四:删除缓存标签 | 快速临时修复 | 治标不治本 | ⭐⭐ |
---
## 🎯 推荐操作流程
### 第一步:检查镜像是否已经成功
```bash
# 在本地或云效中运行
docker pull jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner:latest
```
**如果拉取成功:**
- ✅ 镜像已经构建并推送成功
- ✅ 可以忽略缓存错误
- ✅ 直接部署即可
**如果拉取失败:**
- ❌ 需要修复构建配置
- 继续下面的步骤
### 第二步:修改云效配置
使用**方案一**(推荐)或**方案二**修改流水线配置。
### 第三步:重新运行构建
保存配置后,重新触发构建。
### 第四步:验证部署
```bash
# 查看 K8s 中的 Pod
kubectl get pods -l app=skillhub-scanner
# 查看 Pod 日志
kubectl logs -l app=skillhub-scanner --tail=50
# 测试健康检查
kubectl exec -it <pod-name> -- wget -qO- http://localhost:8000/health
```
---
## 💡 为什么会有缓存冲突?
可能的原因:
1. **并发构建**
- 多个构建任务同时写入同一个缓存标签
- 云效的 `flow-docker-build-cache` 是固定标签名
2. **缓存标签被锁定**
- 上一次构建异常退出,缓存标签处于锁定状态
- 镜像仓库的缓存管理机制问题
3. **权限问题**
- 构建账号对缓存标签没有覆盖权限
- 镜像仓库配置了只读策略
---
## 📞 还是无法解决?
如果以上方案都无法解决,可能需要:
1. **联系云效技术支持**
- 确认云效的 Docker 构建机制
- 是否可以禁用默认的缓存行为
2. **联系阿里云容器镜像服务**
- 检查镜像仓库配置
- 确认缓存标签的权限设置
3. **使用其他构建方式**
- 在云效外部构建(如本地或 GitHub Actions)
- 只用云效做部署
---
## 📝 使用我提供的 .flow.yml
我已经创建了一个完整的流水线配置文件:`scanner/.flow.yml`
**使用步骤:**
1. 提交文件到 Git
```bash
git add scanner/.flow.yml
git commit -m "feat: 添加禁用缓存的流水线配置"
git push
```
2. 在云效中配置
- 进入 Flow 流水线
- 点击"编辑" → "流水线即代码"
- 选择"使用代码库中的配置文件"
- 文件路径:`scanner/.flow.yml`
- 保存
3. 运行构建
- 点击"运行"
- 观察构建日志
这个配置使用 `docker build`(不是 buildx),完全避免了缓存冲突问题。

View file

@ -3,9 +3,6 @@ FROM jsessh-registry.cn-shanghai.cr.aliyuncs.com/base-images/python:latest
WORKDIR /app
# 配置阿里云 yum 镜像源(可选,基础镜像可能已配置)
RUN sed -i 's|releasever|3|g' /etc/yum.repos.d/*.repo 2>/dev/null || true
# 升级 pip
RUN pip install --upgrade pip \
-i https://mirrors.aliyun.com/pypi/simple/ \
@ -13,33 +10,50 @@ RUN pip install --upgrade pip \
--retries 5 \
--trusted-host mirrors.aliyun.com
# 安装编译依赖和 Python 包
RUN yum install -y \
gcc \
gcc-c++ \
make \
glibc-devel \
libffi-devel \
openssl-devel \
wget && \
# 检查 yum 配置并安装依赖
RUN set -ex && \
echo "=== 检查 yum 仓库配置 ===" && \
yum repolist || echo "repolist failed" && \
echo "" && \
echo "=== 清理 yum 缓存 ===" && \
yum clean all && \
rm -rf /var/cache/yum && \
echo "" && \
echo "=== 更新 yum 元数据 ===" && \
yum makecache || yum makecache fast || true && \
echo "" && \
echo "=== 安装编译依赖 ===" && \
yum install -y \
gcc \
gcc-c++ \
make \
glibc-devel \
libffi-devel \
openssl-devel \
wget \
ca-certificates && \
echo "" && \
echo "=== 安装 Python 包 ===" && \
pip install --no-cache-dir \
-i https://mirrors.aliyun.com/pypi/simple/ \
--timeout 120 \
--retries 5 \
--trusted-host mirrors.aliyun.com \
--extra-index-url https://pypi.tuna.tsinghua.edu.cn/simple \
cisco-ai-skill-scanner && \
-i https://mirrors.aliyun.com/pypi/simple/ \
--timeout 120 \
--retries 5 \
--trusted-host mirrors.aliyun.com \
--extra-index-url https://pypi.tuna.tsinghua.edu.cn/simple \
cisco-ai-skill-scanner && \
echo "" && \
echo "=== 清理编译依赖 ===" && \
yum remove -y \
gcc \
gcc-c++ \
make \
glibc-devel \
libffi-devel \
openssl-devel && \
gcc \
gcc-c++ \
make \
glibc-devel \
libffi-devel \
openssl-devel && \
yum clean all && \
rm -rf /var/cache/yum
# 创建 app 用户和组(RHEL 语法)
# 创建 app 用户和组
RUN groupadd -r app && \
useradd -r -g app -s /sbin/nologin app && \
mkdir -p /tmp/skillhub-scans && \
@ -49,7 +63,6 @@ USER app
EXPOSE 8000
# 健康检查
HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8000/health || exit 1

28
scanner/check-image.sh Executable file
View file

@ -0,0 +1,28 @@
#!/bin/bash
# 检查镜像是否已经成功推送
IMAGE_NAME="jsessh-registry.cn-shanghai.cr.aliyuncs.com/apps/sh-skill-scanner"
echo "========================================="
echo "检查镜像仓库中的镜像"
echo "========================================="
# 检查 latest 标签
echo "检查 latest 标签..."
docker pull ${IMAGE_NAME}:latest && echo "✅ latest 标签存在" || echo "❌ latest 标签不存在"
echo ""
# 列出所有标签(需要 aliyun CLI)
if command -v aliyun &> /dev/null; then
echo "列出所有标签..."
aliyun cr GET /repos/apps/sh-skill-scanner/tags || echo "无法列出标签"
else
echo "💡 提示: 安装阿里云 CLI 可以列出所有标签"
echo " aliyun cr GET /repos/apps/sh-skill-scanner/tags"
fi
echo ""
echo "========================================="
echo "检查完成"
echo "========================================="