GitHub Actions部署时Docker拉取ghcr.io镜像报unauthorized如何解决
问题根因
- GitHub Actions中「Log in to GitHub Packages」步骤的登录状态仅保存在当前Actions运行器本地,不会同步到你的DigitalOcean Droplet,因此Droplet拉取ghcr.io私有镜像时自然没有认证权限。
- 手动执行
docker login时触发交互式密码输入,是因为-p参数传递的变量未被正确识别,docker会忽略无效的密码参数转而要求手动输入。 - 你的部署脚本存在文件名不匹配问题:scp上传的是
docker-compose_prod.yml,但后续docker-compose命令调用的是docker-compose.prod.yml,即使认证成功也会找不到配置文件。
修复方案
- 首先确认你的GitHub Personal Access Token(PAT)权限配置正确:必须勾选
read:packages权限,如果镜像属于组织,还要确保PAT被授予对应组织的包访问权限。 - 替换Droplet上的docker登录命令,使用标准输入传参的写法,完全避免交互式密码校验:
echo $PERSONAL_ACCESS_TOKEN | docker login ghcr.io -u $NAMESPACE --password-stdin
- 修正你的GitHub Actions部署脚本,将认证变量同步到Droplet,同时修正文件名不匹配问题:
- name: Build and deploy images on DigitalOcean env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} NAMESPACE: ${{ secrets.NAMESPACE }} run: | # 把认证变量追加到.env文件,同步到Droplet echo "PERSONAL_ACCESS_TOKEN=${PERSONAL_ACCESS_TOKEN}" >> ./.env echo "NAMESPACE=${NAMESPACE}" >> ./.env scp -o StrictHostKeyChecking=no -r ./.env ./docker-compose_prod.yml root@${{ secrets.DIGITAL_OCEAN_IP_ADDRESS }}:/app ssh -o StrictHostKeyChecking=no root@${{ secrets.DIGITAL_OCEAN_IP_ADDRESS }} << 'ENDSSH' cd /app source .env # 使用标准输入方式登录,不会触发密码输入 echo $PERSONAL_ACCESS_TOKEN | docker login ghcr.io -u $NAMESPACE --password-stdin docker pull $WEB_IMAGE docker pull $NGINX_IMAGE # 修正文件名,和上传的文件保持一致 docker-compose -f docker-compose_prod.yml up -d ENDSSH
- 手动验证时,先执行
echo $NAMESPACE和echo $PERSONAL_ACCESS_TOKEN确认变量已正确加载,再执行登录命令即可完成非交互式认证。
内容的提问来源于stack exchange,提问作者Joseph Adam
相关产品推荐
相关产品推荐

