GitLab私有容器仓库登录失败问题求助
从你提供的日志、配置和流水线输出来看,核心问题大概率是GitLab Registry的外部URL配置和实际访问地址不匹配,加上反向代理(Traefik)的Host头转发错误,导致认证流程失败。下面是一步步的排查和解决方法:
1. 先修正Registry外部URL与实际访问地址的一致性
你的Registry日志里有个明显的矛盾点:
2018-06-02_19:27:03.50891 time="2018-06-02T19:27:03.50886204Z" level=warning msg="error authorizing context: authorization token required" ... http.request.host="registry.gitlab.MYDOMAIN:4567" ...
但你实际执行docker login用的地址是gitlab.MYDOMAIN:4501,这说明反向代理把请求转发到了GitLab内部的Registry端口(4567),并且修改了Host头,而GitLab Registry的external_url配置和实际访问地址不匹配,导致GitLab的认证服务无法识别这个请求,直接拒绝了。
具体操作:
- 把
GITLAB_OMNIBUS_CONFIG里的registry_external_url改成和你实际访问完全一致的地址,不要用变量,直接写死:
改完后重启GitLab容器让配置生效。registry_external_url 'https://gitlab.MYDOMAIN:4501' - 检查Traefik的反向代理规则,确保转发
gitlab.MYDOMAIN:4501的请求时,保留原始Host头。Traefik需要在对应的路由配置里加上passHostHeader: true,这样Registry才能收到正确的访问地址。
2. 确认项目的容器仓库功能已经开启
即使GitLab全局开了Registry,单个项目也得手动启用:
- 进入你的项目 → 设置 → 通用 → 可见性、项目功能、权限
- 找到容器注册表选项,确保它是开启状态
- 保存后,确认项目页面里显示的容器仓库地址和你用的
$CI_REGISTRY_IMAGE完全一致
3. 验证Docker的Insecure Registry配置(如果没用到可信SSL证书)
你在CI的docker:dind服务里加了--insecure-registry=gitlab.MYDOMAIN:4501,但本地机器也得同步配置:
- 编辑本地Docker的配置文件
/etc/docker/daemon.json,添加以下内容:{ "insecure-registries": ["gitlab.MYDOMAIN:4501"] } - 重启Docker服务:
sudo systemctl restart docker - CI这边的配置看起来没问题,但可以检查Runner的日志,有没有关于Registry连接的警告信息。
4. 确认CI变量的正确性
你在.gitlab-ci.yml里写的是docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY,但流水线实际执行的是docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY——这其实是正常的,因为GitLab会自动把$CI_REGISTRY_USER设为gitlab-ci-token,$CI_REGISTRY_PASSWORD设为$CI_BUILD_TOKEN。不过可以手动验证下变量:
在before_script里加两行:
echo "CI_REGISTRY地址:$CI_REGISTRY" echo "CI_REGISTRY_USER:$CI_REGISTRY_USER"
确认输出的CI_REGISTRY是https://gitlab.MYDOMAIN:4501,和你配置的external_url一致。
5. 手动验证Registry的认证流程
在本地机器上用curl测试下Registry的接口,看看认证跳转是否正常:
curl -v https://gitlab.MYDOMAIN:4501/v2/
正常情况下应该返回401 Unauthorized,并且包含类似这样的响应头:
WWW-Authenticate: Bearer realm="https://gitlab.MYDOMAIN/jwt/auth",service="container_registry"
如果返回的realm地址不对(比如带了内部域名或端口),那肯定是external_url配置错了,导致认证跳转地址错误。
另外,用个人账号登录时,建议用个人访问令牌代替密码,并且令牌要勾选read_registry和write_registry权限:
- 进入GitLab个人设置 → 访问令牌 → 创建新令牌,勾选这两个权限
- 然后用这个令牌登录:
docker login -u 你的用户名 -p 你的个人访问令牌 gitlab.MYDOMAIN:4501
6. 检查端口映射是否正确
确认GitLab容器的4501端口已经正确映射到宿主机的4501端口,并且Traefik确实把这个端口的流量转发到了GitLab容器内部的Registry服务端口(默认是5000,如果你没修改过的话)。
按照上面的步骤逐一排查,最优先解决的是Registry外部URL和反向代理Host头的问题,这两个是导致access forbidden的最常见原因。
内容的提问来源于stack exchange,提问作者kwinkel

