Jenkins Pipeline无法推送Docker镜像:Registry认证失败求助
问题描述
此前长期运行正常的Jenkins Pipeline,近期突然因Docker Registry认证错误失败,错误信息如下:
unauthorized: User is unauthorized to upload to docker-registry/kong/k/_uploads
未对Pipeline脚本做任何修改,以下是出现问题的Pipeline脚本:
// scripted pipeline // script properties with input parameters.Version as string input parameter properties([ parameters([ string(defaultValue: 'latest', description: '', name: 'tag', trim: false) ]) ]) def registry = [ url : 'docker-registry-url', credentials: "creds" ] node('dockerhost'){ stage('checkout'){ cleanWs() checkout scm } stage('build'){ // check if file kong_v.txt exists if(fileExists(file: 'kong_v.txt')){ docker.image('python:3.9').withRun() { c -> sh "pip3 install jinja2 pyyaml schema" sh "python3 generate_dockerfile.py > Dockerfile" } // parse file, split by new line, filter out comments and empty strings. def kong_versions = readFile('kong_v.txt').split('\n').findAll{line -> line.startsWith('#') == false && line.isEmpty() == false } // for each kong version build docker image kong_versions.each{kong_version -> kong_version = kong_version.trim() withDockerRegistry(url:"https://$registry.url" ,credentialsId:"$registry.credentials"){ sh "docker build --build-arg=KONG_VERSION=$kong_version -t $registry.url/kong/kong-$k:$tag ." sh "docker push $registry.url/kong/kong-$k:$tag" } } } else { throw new Exception("kong_v.txt file not found") } } }
排查与修复要点
1. 核心问题:未定义变量导致镜像路径异常
脚本中构建和推送命令使用了$k变量,但这个变量从未被定义过,导致镜像标签变成kong-/,最终推送的路径异常(对应错误信息里的docker-registry/kong/k/_uploads)。Registry会对异常路径做权限校验,自然返回未授权。
修复:把kong-$k改成kong-$kong_version,使用循环中定义的kong_version变量,确保镜像路径正确,比如:
sh "docker build --build-arg=KONG_VERSION=$kong_version -t $registry.url/kong/kong-$kong_version:$tag ." sh "docker push $registry.url/kong/kong-$kong_version:$tag"
2. 凭证有效性检查
虽然未修改脚本,但Jenkins中配置的creds凭证可能出现以下情况:
- 凭证的密码/Token过期
- Docker Registry端调整了该用户的权限,使其失去对应仓库的写入权限
- 凭证本身被误修改(比如ID变更,但脚本里还是用旧的
creds)
检查方式:登录Jenkins,进入「凭证管理」找到creds,验证凭证内容是否正确,同时在Registry端确认用户权限。
3. Docker Registry URL格式验证
withDockerRegistry中的URL如果是https://$registry.url,要确认registry.url本身是否已经包含https://,如果重复添加协议,会导致认证地址错误,进而触发未授权。
修复:统一URL格式,比如如果registry.url是docker-registry.example.com,则withDockerRegistry的url参数写https://$registry.url;如果registry.url已经是https://docker-registry.example.com,则去掉重复的https://。
4. 容器执行命令的逻辑错误(非直接导致认证,但需修复)
脚本中docker.image('python:3.9').withRun()的用法错误,withRun()只是启动容器,后续的sh命令是在Jenkins节点宿主机执行的,而非容器内部。如果宿主机没有Python环境,这部分代码早就失败了,只是刚好宿主机有Python才没出问题。
修复:改用inside()方法进入容器执行命令:
docker.image('python:3.9').inside() { sh "pip3 install jinja2 pyyaml schema" sh "python3 generate_dockerfile.py > Dockerfile" }
内容的提问来源于stack exchange,提问作者poisoned_monkey

