示例说明
手工 docker build/tag/push 三连容易漏标签或推错仓——脚本把流程钉死。镜像标签以 git SHA 为主键:可追溯回具体提交,latest 只是移动指针;构建参数与 OCI 标准标签把修订号与时间写进镜像元数据,registry 里可查。推送后的 digest 是不可变指纹,manifest 探测确认多架构清单在 registry 真正就绪——推送命令成功不等于立即可拉。
技术要点
- git SHA 作为镜像主标签可追溯
- OCI 标准标签内建镜像元数据
- manifest 探测确认 registry 就绪
代码解读
前置检查包括 docker 存在与工作区干净——脏工作区构建的镜像无法对应任何提交;build 传修订号构建参数并打两个标签。push_and_verify 推送后从 RepoDigests 提取 digest 展示,manifest inspect 的 until 循环最多五次每次三秒——多架构镜像的 manifest 聚合有延迟。
使用建议
latest 标签仅作便捷指针,部署清单永远钉 SHA 或 digest。构建缓存与多架构构建按 CI 能力叠加。registry 凭据走 docker login 的外部配置。
代码示例
#!/usr/bin/env bash
set -euo pipefail
readonly REGISTRY="registry.example.com"
readonly IMAGE="${REGISTRY}/billing-api"
readonly GIT_SHA="$(git rev-parse --short=12 HEAD)"
die() { echo "Error: $*" >&2; exit 1; }
command -v docker >/dev/null || die "docker 未安装"
git diff --quiet || die "工作区不干净,先提交再发布"
build() {
echo "构建 ${IMAGE}:${GIT_SHA}"
docker build \
--build-arg GIT_COMMIT="${GIT_SHA}" \
--label "org.opencontainers.image.revision=${GIT_SHA}" \
--label "org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-t "${IMAGE}:${GIT_SHA}" \
-t "${IMAGE}:latest" \
.
}
push_and_verify() {
docker push "${IMAGE}:${GIT_SHA}"
docker push "${IMAGE}:latest"
local digest
digest=$(docker inspect --format '{{index .RepoDigests 0}}' \
"${IMAGE}:${GIT_SHA}" | cut -d@ -f2)
echo "已推送: ${IMAGE}@${digest}"
# registry 健康探测:清单可拉取才算发布完成
local attempt=0
until docker manifest inspect "${IMAGE}:${GIT_SHA}" >/dev/null 2>&1; do
(( attempt++ )) || true
(( attempt < 5 )) || die "manifest 未就绪,registry 可能异常"
sleep 3
done
echo "发布完成:${GIT_SHA}"
}
build
push_and_verify