github actions 可通过原生 step.retry、build-push-action 的 push-retry 参数或自定义 shell 脚本实现 docker push 重试,推荐优先使用 step.retry;需区分临时错误与永久错误,避免盲目重试加重服务压力。

GitHub Actions 本身不直接提供 docker push 的重试能力,但可以通过原生配置、组合动作或封装逻辑实现可靠重试。关键不是“有没有重试”,而是“怎么让重试既有效又不加重服务压力”。
用 steps.retry 直接启用平台级重试
这是最简洁、推荐优先使用的方式。GitHub Actions 原生支持对单个 step 设置重试次数和条件,适用于登录、构建、推送等任意步骤:
- 在
uses: docker/login-action@v2或uses: docker/build-push-action@v4步骤中添加if: always()和retry配置 - 支持最大 3 次重试(GitHub 限制),失败后自动等待 1–5 秒再重试(指数退避由平台内部处理)
- 仅对网络超时、HTTP 502/503/429 等临时错误生效,不会重试权限拒绝(
denied)或标签错误等永久性问题
示例写法:
- name: Push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: myorg/myapp:${{ github.sha }}
if: always()
retry:
max_attempts: 3
用 build-push-action 内置重试参数
docker/build-push-action@v4 自带 push-retry 选项,比 step-level retry 更聚焦推送环节:
- 设置
push-retry: 3,会在docker push失败时自动重试,且默认启用指数退避 - 它只作用于 push 阶段,不影响构建或登录;适合已确认镜像构建成功、只需保障上传稳定的场景
- 配合
cache-from和cache-to使用,可避免重试时重复构建
注意:该参数需搭配 push: true 才生效,且不覆盖 step-level retry。
自定义 shell 脚本封装重试逻辑
当需要更精细控制(如自定义退避时间、记录失败原因、跳过特定错误码),可绕过 action,用 run 执行带重试的 shell:
- 手动实现指数退避(如第 1 次等 1s,第 2 次等 2s,第 3 次等 4s)
- 用
grep -q "unauthorized"过滤掉认证类错误,避免无效重试 - 结合
timeout 300s防止某次推送卡死阻塞整个 workflow
典型结构:
- name: Push with custom retry
run: |
MAX=3
DELAY=1
for i in $(seq 1 $MAX); do
echo "Push attempt $i..."
if docker push my-registry/app:${{ github.sha }}; then
exit 0
fi
if [[ $i -eq $MAX ]]; then exit 1; fi
sleep $DELAY
DELAY=$((DELAY * 2))
done
规避重试陷阱的实用建议
重试不是万能解药,盲目开启反而可能掩盖真实问题:
- 先确保
docker login成功——重试不会修复凭证错误,只会反复失败 - 检查镜像大小:超过 500MB 的镜像易触发超时,建议用多阶段构建压缩体积
- 私有 Registry 若启用了限流(如 Harbor 的 rate limit),需在服务端调高阈值,否则重试会加剧被限
- 不要对所有步骤统一设
retry: 3,应按需启用,尤其避免在测试失败后重试推送
真正稳定的推送,靠的是“正确配置 + 适度重试 + 可观测性”。把失败日志保留下来,比单纯多试几次更有价值。











