gitlab-ce 的简单使用

news/2026/1/19 17:46:48/文章来源:https://www.cnblogs.com/daveyhe/p/19503157

gitlab-ce 的简单使用

简单认识 gitlab-ce

以下理解是个人理解,细节的正确性请做测试验证 😃。

请求流程:

# HTTP/HTTPS 请求
客户端 (浏览器/终端)|| HTTP/HTTPS 请求 (如克隆仓库、访问网页)v
外部 Nginx 反向代理|| 转发动态请求到 Workhorsev
GitLab Workhorse (处理静态资源/文件上传)|| 1. 静态资源直接响应| 2. 动态请求转发到 Puma|    ┌───────────────┐|    │               │v    v               v
Puma (Rails 应用)    Gitaly (Git 操作)|    │               │|    │ 业务逻辑处理   │ 处理 git clone/push 等操作|    │ (用户认证/API) │ (读取/写入仓库数据)|    │               │v    v               v
PostgreSQL (存储元数据)    仓库文件系统(用户/项目配置/权限)    (实际代码存储)|| 3. 后台任务 (如邮件发送)v
Sidekiq (异步任务队列)|v
Redis (缓存/任务队列存储)# GitLab Shell
GitLab Shell(SSH) --> Gitaly(权限验证后操作仓库)|| 1. 认证用户| 2. 权限验证|    ┌───────────────┐|    │               │v    v               v
SSH 客户端    Gitaly (权限操作)|    │               │|    │ 校验用户权限   │ 执行 git 操作|    │ (公钥/密钥)    │ (读取/写入仓库数据)|    │               │v    v               v
仓库文件系统    PostgreSQL (存储权限)(用户/项目权限)    (实际代码存储)# Registry 镜像仓库访问
Registry 容器镜像仓库|| 1. 存储镜像元数据| 2. 镜像访问(如拉取、推送)|    ┌───────────────┐|    │               │v    v               v
Nginx 反向代理    PostgreSQL (镜像元数据)(镜像配置/权限)    (镜像文件存储)

GitLab 各组件通过数据交互和功能协作实现整体运行,其核心组件的依赖关系及作用:

  • 前端与反向代理层 Nginx(默认启用)
    • 作为反向代理,处理外部 HTTP/HTTPS 请求,转发至后端服务(如 GitLab Workhorse、Puma)。
    • 负责 SSL 证书管理、请求路由和静态资源(如图片、CSS)的直接响应。
  • GitLab Workhorse
    • 接收 Nginx 转发的动态请求(如 API、Webhook),处理文件上传、反向代理至 Puma,并管理与 Gitaly 的通信。
  • Puma(Ruby 应用服务器)
    • 运行 GitLab Rails 应用,处理业务逻辑(如用户认证、项目管理、API 接口)。
    • 依赖 Redis 和 PostgreSQL 存储数据,通过 GitLab Workhorse 与 Gitaly 交互。
  • GitLab Shell
    • 处理 SSH 协议的 Git 操作(如克隆、推送代码),通过配置文件(config.yml)与 GitLab Rails 通信,验证用户权限。
  • 数据存储与缓存层
    • PostgreSQL:存储 GitLab 的元数据(用户信息、项目配置、权限关系等)。
      • Puma 通过 ActiveRecord 访问数据库,部分组件(如 Sidekiq)也依赖其数据。
    • Redis:缓存会话数据、计数器、任务队列(Sidekiq),提升访问速度。
      • Puma、Sidekiq、GitLab Workhorse 均需连接 Redis。
  • Git 仓库处理核心
    • Gitaly(Git 仓库管理服务)负责处理所有 Git 操作(克隆、拉取、推送),优化大仓库性能。
      • Puma、GitLab Shell、GitLab Workhorse 通过 UNIX socket 或 TCP 连接 Gitaly,避免直接操作文件系统。
  • 辅助服务与扩展
    • Sidekiq(后台任务处理器)异步处理耗时任务(如邮件发送、CI/CD 流水线调度),依赖 Redis 存储任务队列,从 PostgreSQL 获取任务数据。
    • Registry(容器镜像仓库)若启用,需独立运行并连接 PostgreSQL 存储镜像元数据,通过 Nginx 暴露访问端口。

Workhorse 和 Puma 是两个核心组件:

  • GitLab Workhorse
    • 高性能反向代理和请求处理器,用 Go 语言开发。
      • 请求过滤与转发:静态资源直接响应(如图片),接收 Nginx 转发的动态请求(如 API、Webhook、文件上传),过滤非法请求后转发给 Puma。
      • 文件处理优化:处理大文件上传(如 LFS 对象),支持断点续传,避免 Puma 直接处理导致的性能瓶颈。
      • 与 Gitaly 通信:负责 Git 操作(如克隆、拉取)的网络请求,直接对接 Gitaly 服务。
      • 安全控制:管理会话 cookie、校验请求头,防止恶意访问。
  • Puma
    • Ruby 应用服务器,运行 GitLab Rails 应用的容器,用 Ruby 语言开发。
      • 业务逻辑处理:执行 Ruby 代码,处理用户认证、项目管理、页面渲染等核心业务逻辑。
      • 数据交互:访问 PostgreSQL 数据库和 Redis 缓存,生成响应内容(如 HTML、JSON)。
      • 多进程/线程模型:通过配置 worker_processesthreads 实现并发处理,提升请求吞吐量。

Puma​ 作为应用服务器,必须通过与 Workhorse 相同的协议(TCP 或 Unix Socket)响应请求:

  • 多节点集群​,使用 TCP 通信:
    • 客户端 --> Workhorse (TCP port_a)
    • Workhorse --> Puma (TCP port_b)
      • 配置 gitlab_workhorse['auth_backend'] = "http://puma_ip:puma_port"
    • Puma 处理请求并返回响应。
  • 单节点部署​,优先使用 Unix Socket,避免网络协议栈开销,安全性更好(通过文件权限控制访问):
    • 客户端 --> Workhorse (Unix Socket)
    • Workhorse --> Puma (同一个 Unix Socket)
      • 配置 gitlab_workhorse['auth_socket'] = "workhorse_and_puma_are_using_the_same_unix_socket"
    • Puma 处理请求并返回响应。

协议要求一致的原因:

  • 底层 API 不兼容,两者接口不同,无法跨协议通信:
    • TCP 连接使用 connect(IP, PORT) 系统调用。
    • Unix Socket 使用 connect(PATH) 系统调用。
  • 数据传输方式不同:
    • TCP 数据包需经过网络协议栈(IP、TCP 层),包含源/目标 IP 和端口信息。
    • Unix Socket 直接在文件系统中传输数据,无需网络协议头。
  • 地址解析机制不同:
    • TCP 依赖 DNS 或 IP 地址解析。
    • Unix Socket 依赖文件系统路径解析。

常见的 5XX 错误通常是由于 Puma 服务未启动或配置错误导致的,需要注意的是,Puma 服务启动得比较慢,尤其是机器资源比较吃紧时,重启 GitLab 服务后通常需要等待数分钟才能正常响应请求,表现是一开始返回 500 错误后面恢复正常。

安装 gitLab-ce

Docker 部署 gitLab-ce:

sudo mkdir -p /data/gitlab/{data,config,logs}
sudo chown -R 998:998 /data/gitlab
sudo chmod -R 755 /data/gitlab# GitLab 官方镜像默认会以 root 启动,但内部服务会自动切换到 git 用户
# --memory-swap 如果和 --memory 设为 相同值,表示禁用容器使用交换分区(推荐,避免 swap 拖慢性能),如果不设置,默认是 --memory 的 2 倍(比如 -m 2g 会允许 4g 总内存)。
# 上面这部分只是个人认识,具体细节还需要查看官方文档
docker run -d \--name gitlab-ce \-e TZ="Asia/Shanghai" \--restart always \--memory=3.5g \--memory-swap 3.5g \--memory-reservation 2.5g \--cpus=1 \-p 8080:8181 \-p 2222:22 \-p 8081:5000 \-v /data/gitlab/data:/var/opt/gitlab \-v /data/gitlab/config:/etc/gitlab \-v /data/gitlab/logs:/var/log/gitlab \gitlab/gitlab-ce:16.10.0-ce.0# 关闭容器,修改配置 /data/gitlab/config/gitlab.rb
# 以下配置仅供参考,随着 gitlab-ce 版本的更新会存在差异,具体参数根据需求做调整
: <<'NICETOMEETYOU'
# 10.1.0.6 是 gitlab 容器的宿主机 IP
# http://10.1.0.6:8080/ -> 容器内 workhorse 端口 8181 -> 容器内 puma 端口 8080(这里怕混淆的话,调整为其它端口)
external_url 'http://10.1.0.6:8080/'
gitlab_rails['gitlab_ssh_host'] = '10.1.0.6'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
gitlab_workhorse['enable'] = true
gitlab_workhorse['listen_network'] = "tcp"
gitlab_workhorse['listen_addr'] = "0.0.0.0:8181"
gitlab_workhorse['auth_backend'] = "http://localhost:8080"# 配置 Gitaly 超时时间(单位:秒)
gitlab_rails['gitaly_timeout'] = 60# 配置 Sidekiq Gitaly 超时时间(单位:秒)
sidekiq['gitaly_timeout'] = 60# puma 配置
puma['enable'] = true
puma['worker_timeout'] = 60
puma['worker_processes'] = 1
puma['min_threads'] = 1
puma['max_threads'] = 1
puma['listen'] = '127.0.0.1'
puma['port'] = 8080
# 禁用 puma socket 监听
puma['socket'] = ''
puma['somaxconn'] = 10240
puma['per_worker_max_memory_mb'] = 512
nginx['enable'] = false
sidekiq['concurrency'] = 5# 禁用非核心服务
prometheus['enable'] = false
alertmanager['enable'] = false
gitlab_exporter['enable'] = false
node_exporter['enable'] = false
postgres_exporter['enable'] = false
redis_exporter['enable'] = false
mattermost['enable'] = false
gitlab_pages['enable'] = false
gitlab_rails['service_desk_enabled'] = false# 禁用 Elasticsearch
gitlab_rails['elasticsearch_enabled'] = false# registry 配置,暂时忽略
...
NICETOMEETYOU

外部可配置一个 Nginx 反向代理来访问,并且配置 SSL 证书:https://registry.yourdomain.com:8689,配置可参考后面的 Registry 中的 Nginx 反向代理。

Nginx 反向代理使用的 SSL 证书可使用 Certbot 之类的工具来申请、延期证书。

几个简单的问题排查命令:

# 实时查看日志
docker logs -f gitlab-ce# 查看初始 root 密码
sudo cat /data/gitlab/config/initial_root_password
# Password: JBEdFMJuYoW3VDnDUPR8BNL+5ENyZP2jTsdVWtAzswM=# 进入容器排查问题
docker exec -it gitlab-ce bash# 进入容器后
> gitlab-ctl status
# 实时查看 puma 日志
> tail -f /var/log/gitlab/puma/current# 浏览器端创建/删除分支报 4:Deadline Exceeded
# 查看所有 GitLab 服务状态(重点关注 gitaly/redis/postgresql/puma)
> gitlab-ctl status# 实时查看 Gitaly 日志(分支操作的底层日志)
> gitlab-ctl tail gitaly | grep -i "deadline\|timeout\|error"# 实时查看 Puma 日志(前端请求超时)
> gitlab-ctl tail puma | grep -i "deadline\|timeout\|error"# 查看 Redis 日志(确认是否仍有连接异常)
> gitlab-ctl tail redis | grep -i "EOF\|error"# 查看 PostgreSQL 日志(比如分支元数据存储超时)
> gitlab-ctl tail postgresql | grep -i "timeout\|lock\|error"

启用 Registry 功能

内部测试时可能会用到 GitLab 内置的 Container Registry 功能。

按照我自己的经验,使用 Registry 通常需要会使用一个外部的 nginx 反向代理,将外部请求转发到 GitLab 内置的 Container Registry 服务,另外由于需要与其他系统集成比如在 K8s、Jenkins 等中使用,通常需要给 Registry 配置一个域名来访问,并且该域名配置使用 SSL 证书。

修改 gitlab.rb

# 10.1.0.6 是 gitlab 容器的宿主机 IP
# registry_external_url -> 容器内 registry 端口 5000
registry_external_url 'http://10.1.0.6:8081/'
gitlab_rails['registry_enabled'] = true
gitlab_rails['registry_host'] = "10.1.0.6"
registry['enable'] = true
registry['registry_http_addr'] = "0.0.0.0:5000"
registry_nginx['enable'] = false
  • registry_external_url:对外公开访问的 Registry 地址,这里我后面会另外套一层 Nginx 反向代理(配置 SSL),将外部请求转发到容器内的 registry 服务。
    • 用户浏览器和 Docker CLI 使用。
  • gitlab_rails['registry_enabled']:GitLab Rails 应用(即 GitLab 网页界面和 API),控制 GitLab 是否集成 Container Registry 功能。
    • true:启用集成,gitlab 项目页面显示 “Container Registry” 菜单,允许用户通过 GitLab 管理镜像。
      • 项目地址 --> 部署 --> Container Registry
        • https://git.yourdomain.com:8688/dev/demo/container_registry
          • 这里的 https://git.yourdomain.com:8688 是 GitLab 的访问地址。
    • false:禁用集成,gitlab 项目页面隐藏 Registry 菜单,无法通过 GitLab 访问或推送镜像(即使 Registry 服务仍在运行)。
  • gitlab_rails['registry_host']:与 registry_external_url 的 IP 保持一致。
  • registry['enable']:GitLab 内置的 Docker Registry 服务(独立于 GitLab Rails 应用),控制是否在当前 GitLab 服务器上运行 内置的 Container Registry 服务。
    • true:启动内置 Registry 服务,监听指定端口(在这里是 10.0.0.13:5000),存储镜像文件。
    • false:关闭内置 Registry 服务,适用于使用 外部 Registry(如 Harbor、Docker Hub 或自建 Registry)的场景。
  • registry['registry_http_addr']:Registry 服务监听地址。
  • registry_nginx['enable']:是否启用 Nginx 反向代理。
    • 这里设置为 false,因为我使用了外部 nginx 反向代理。

配置 nginx:

upstream gitlab-registry {server 10.1.0.6:8081 fail_timeout=0;keepalive 64;
}map $http_upgrade $connection_upgrade_gitlab_ssl {default upgrade;''      close;
}server {listen 8689 default ssl;server_name registry.yourdomain.com;server_tokens off; ## Don't show the nginx version number, a security best practicessl_certificate /usr/local/nginx/conf/ssl/registry.yourdomain.com/fullchain1.pem;ssl_certificate_key /usr/local/nginx/conf/ssl/registry.yourdomain.com/privkey1.pem;# GitLab needs backwards compatible ciphers to retain compatibility with Java IDEsssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;ssl_prefer_server_ciphers on;ssl_session_cache shared:SSL:10m;ssl_session_timeout 5m;client_max_body_size 0;client_body_buffer_size 16k;client_body_timeout 600;location / {gzip off;proxy_connect_timeout 600;proxy_send_timeout 600;proxy_read_timeout 600;proxy_buffering off;# proxy_set_header    Host                $http_host;proxy_set_header    Host                $host:$server_port;  # 传递代理域名和端口proxy_set_header    X-Real-IP           $remote_addr;proxy_set_header    X-Forwarded-Ssl     on;proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;proxy_set_header    X-Forwarded-Proto   $scheme;proxy_set_header    Upgrade             $http_upgrade;proxy_set_header    Connection          $connection_upgrade_gitlab_ssl;proxy_redirect off;# WebSocket 支持(用于 CI/CD 终端和实时功能)proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_pass http://gitlab-registry$request_uri;}# 静态资源优化location ~ ^/(assets|system|uploads)/ {proxy_cache off;proxy_buffering off;expires max;access_log off;add_header Cache-Control public;proxy_pass http://gitlab-registry$request_uri;}error_page 404 /404.html;error_page 422 /422.html;error_page 500 /500.html;error_page 502 /502.html;error_page 503 /503.html;location ~ ^/(404|422|500|502|503)\.html$ {root /home/git/gitlab/public;internal;}access_log  /data/logs/nginx_logs/gitlab_registry_proxy_8689_access.log;error_log   /data/logs/nginx_logs/gitlab_registry_proxy_8689_error.log;
}

登录 Gitlab 对应的项目管理界面,针对当前项目生成新令牌:

  • 访问对应的项目地址
    • http://10.1.0.6:8080/dev/demo.git/https://git.yourdomain.com:8688/dev/demo.git
  • 设置 -> 个人访问令牌 -> 添加新令牌
    - 令牌名称:gitlab-ci-token,令牌:glpat-fxxxx
    - 选择角色:Developer
    - 选择范围:
    - api
    - read_api
    - read_repository
    - write_repository
    - read_registry
    - write_registry

简单的测试:

# 登录 GitLab Registry
docker login 10.1.0.6:8081 -u gitlab-ci-token -p glpat-fxxxx# 推送镜像到 GitLab Registry
docker push 10.1.0.6:8081/dev/demo/hello-k8s:v1

若在 K8s 中连接使用 Registry,则需要使用对应的 Nginx 反向代理地址 registry.yourdomain.com:8689

# 测试使用 SSL 连接 Registry 服务
openssl s_client -connect registry.yourdomain.com:8689 -servername registry.yourdomain.com# 简单测试,若返回权限问题说明配置正确,无需关心是否能返回镜像列表
curl -v -k https://registry.yourdomain.com:8689/v2/_catalog# 登录 GitLab Registry
docker login registry.yourdomain.com:8689 -u gitlab-ci-token -p glpat-fxxxx# 构建测试镜像
docker build -f Dockerfile.test -t registry.yourdomain.com:8689/dev/demo/hello-k8s:v2 .# 推送镜像到 GitLab Registry
docker push registry.yourdomain.com:8689/dev/demo/hello-k8s:v2# 修改为 GitLab Registry 地址生成新的镜像拉取密钥
GITLAB_REGISTRY="registry.yourdomain.com:8689"
GITLAB_USERNAME="gitlab-ci-token"
GITLAB_PAT="glpat-fxxxx"
SECRET_NAME="gitlab-registry-secret"# 在 K8s 中创建镜像拉取密钥
kubectl create secret docker-registry $SECRET_NAME \--docker-server=$GITLAB_REGISTRY \--docker-username=$GITLAB_USERNAME \--docker-password=$GITLAB_PAT \--docker-email="xxx@example.com"# 测试从 GitLab Registry 拉取镜像
tee test-gitlab-registry.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:name: test-gitlab-registry
spec:containers:- name: hello-k8simage: registry.yourdomain.com:8689/dev/demo/hello-k8s:v2imagePullSecrets:- name: gitlab-registry-secret
EOF
kubectl apply -f test-gitlab-registry.yaml# 查看 Pod 状态
kubectl get pods test-gitlab-registry
# NAME                   READY   STATUS    RESTARTS      AGE
# test-gitlab-registry   1/1     Running   6 (40s ago)   3m35s

GitLab Registry 宿主机的代理问题导致登录失败的排查

由于 Docker 客户端机器通常需要访问 Dockerhub 官网,针对这个配置了全局代理,这个代理会导致本机 Docker 客户端无法直接连接到 GitLab Registry,以下简单的排查思路可供参考。

使用令牌登录 Registry 报错:

$ docker login registry.yourdomain.com:8689
Login did not succeed, error: Error response from daemon: Get "https://registry.yourdomain.com:8689/v2/": EOF
Username (testuser): testuser
Password: 
Error response from daemon: Get "https://registry.yourdomain.com:8689/v2/": EOF

在 Nginx 代理服务器上使用 sudo tcpdump -i any port 8689 -n 以及查看代理 nginx 的访问日志,没有看到任何响应,说明代理 nginx 没有收到请求。

使用 strace 追踪 docker 进程:

$ sudo strace -e trace=openat,read,network -s 1024 -f -p $(pgrep dockerd)
# Docker 客户端向 api.moby.localhost 发送认证请求(POST /v1.49/auth),认证信息包含用户名 testuser 和 GitLab 访问令牌(glpat-*),目标仓库为 registry.yourdomain.com:8689。
[pid 76329] read(21, "POST /v1.49/auth HTTP/1.1\r\nHost: api.moby.localhost\r\nUser-Agent: Docker-Client/28.1.1 (linux)\r\nContent-Length: 103\r\nContent-Type: application/json\r\n\r\n{\"username\":\"testuser\",\"password\":\"glapt-xxxx\",\"serveraddress\":\"registry.yourdomain.com:8689\"}\n", 4096) = 253
# Docker 尝试查找私有仓库的自定义证书(/etc/docker/certs.d/registry.yourdomain.com:8689),返回 ENOENT 错误,说明未找到证书文件。
[pid 76329] openat(AT_FDCWD, "/etc/docker/certs.d/registry.yourdomain.com:8689", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
# 创建 TCP 套接字(socket),准备连接代理服务器。
[pid 76329] socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 25
# 代理服务器地址为 10.0.0.1:1080,EINPROGRESS 表示非阻塞连接正在进行中。
[pid 76329] connect(25, {sa_family=AF_INET, sin_port=htons(1080), sin_addr=inet_addr("10.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
[pid 76329] read(21, 0xc000bd8a01, 1)   = -1 EAGAIN (Resource temporarily unavailable)
# getsockopt(SO_ERROR, [0]) 返回 0,表示连接成功。
[pid 76329] getsockopt(25, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
# getpeername 确认对端地址为代理服务器 10.0.0.1:1080。
[pid 76329] getpeername(25, {sa_family=AF_INET, sin_port=htons(1080), sin_addr=inet_addr("10.0.0.1")}, [112->16]) = 0
# 本机地址为 10.0.0.11:53482,显示客户端使用的临时端口。
[pid 76329] getsockname(25, {sa_family=AF_INET, sin_port=htons(53482), sin_addr=inet_addr("10.0.0.11")}, [112->16]) = 0
# 禁用 Nagle 算法
[pid 76329] setsockopt(25, SOL_TCP, TCP_NODELAY, [1], 4) = 0
# 启用 keepalive
[pid 76329] setsockopt(25, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
# 30 秒无活动发送探测包
[pid 76329] setsockopt(25, SOL_TCP, TCP_KEEPIDLE, [30], 4) = 0
# 探测包间隔 15 秒
[pid 76329] setsockopt(25, SOL_TCP, TCP_KEEPINTVL, [15], 4) = 0
# 最多发送 9 次探测包
[pid 76329] setsockopt(25, SOL_TCP, TCP_KEEPCNT, [9], 4) = 0
# SOCKS5 响应头,表示认证方法协商(0 表示“无认证”)。
[pid 76329] read(25, "\5\0", 2)         = 2
# 客户端选择“用户名/密码认证”(方法 2,但代理返回支持 0)。
[pid 76329] read(25, "\5\0\0\1", 4)     = 4
# 认证方法列表长度(0x30 即 48 字节)。
[pid 76329] read(25, "\0\0\0\0\48", 6)  = 6
# -1 表示调用失败,EAGAIN 是具体错误原因,意为 “资源暂时不可用”。
# 在非阻塞 I/O场景中(上面网络套接字设置了 SOCK_NONBLOCK 标志),此时文件描述符中没有可读取的数据,系统不会阻塞等待,而是立即返回 EAGAIN,告诉进程 “现在没数据,稍后再试”。
[pid 76329] read(25, 0xc000276d80, 576) = -1 EAGAIN (Resource temporarily unavailable)
# 读取 fd=25 返回值为 0,表示读取到文件结束(EOF)。
# 对于网络套接字,这通常意味着对方关闭了连接(如 TCP 连接正常关闭,此时读取返回 0 表示没有更多数据,且连接已终止),而对于普通文件,0 表示已读到文件末尾。
[pid 76329] read(25, "", 576)           = 0
# 另一个 fd 同样表示读取到 EOF
[pid 76329] read(21, "", 4096)          = 0

可以看到由于代理 10.0.0.1:1080 的原因导致登录异常。

使用 curl 走 SOCKS5 代理登录 Registry:

$ curl -v --proxy socks5h://10.0.0.1:1080 https://registry.yourdomain.com:8689/v2/
*   Trying 10.0.0.1:1080...
* TCP_NODELAY set
* SOCKS5 communication to registry.yourdomain.com:8689
* SOCKS5 connect to registry.yourdomain.com:8689 (remotely resolved)
* SOCKS5 request granted.
* Connected to 10.0.0.1 (10.0.0.1) port 1080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crtCApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to registry.yourdomain.com:8689 
* Closing connection 0
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to registry.yourdomain.com:8689 

可以确认是由于 SOCKS5 代理导致登录 Registry 异常。

修改 /etc/docker/daemon.json 将域名 *.yourdomain.com 加到 no-proxy 中,然后重启 docker 服务。

{"data-root": "/data/docker","proxies": {"http-proxy": "socks5://10.0.0.1:1080","https-proxy": "socks5://10.0.0.1:1080","no-proxy": "*.yourdomain.com,.example.org,127.0.0.0/8"},"dns": ["127.0.0.1", "8.8.8.8", "8.8.4.4"]
}

再次测试:

$ docker login registry.yourdomain.com:8689
Authenticating with existing credentials... [Username: testuser]i Info → To login with a different account, run 'docker logout' followed by 'docker login'Login Succeeded

需要注意的是,在很多场景下不能完全把代理关闭,因为很多时候还是需要访问 dockerhub 等官方仓库,关闭代理后使用 strace 追踪进程 dockerd 会发现访问 dockerhub 等官方仓库会异常:

[pid 77960] accept4(4, {sa_family=AF_UNIX}, [112->2], SOCK_CLOEXEC|SOCK_NONBLOCK) = 21
# Docker 客户端通过 /run/docker.sock 与守护进程通信。
[pid 77960] getsockname(21, {sa_family=AF_UNIX, sun_path="/run/docker.sock"}, [112->19]) = 0
[pid 77960] accept4(4, 0xc0004499d4, [112], SOCK_CLOEXEC|SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
[pid 77960] read(21, 0xc0003aa000, 4096) = -1 EAGAIN (Resource temporarily unavailable)
# 客户端先发送健康检查请求,确认 Docker 守护进程是否可用。
[pid 77960] read(21, "HEAD /_ping HTTP/1.1\r\nHost: api.moby.localhost\r\nUser-Agent: Docker-Client/28.1.1 (linux)\r\n\r\n", 4096) = 92
[pid 77960] read(21, 0xc0003aa000, 4096) = -1 EAGAIN (Resource temporarily unavailable)
# 客户端发送搜索请求到 Docker API,目标为搜索 mysql 镜像。
[pid 77960] read(21, "GET /v1.49/images/search?term=mysql HTTP/1.1\r\nHost: api.moby.localhost\r\nUser-Agent: Docker-Client/28.1.1 (linux)\r\nX-Registry-Auth: e30=\r\n\r\n", 4096) = 139
[pid 77960] openat(AT_FDCWD, "/etc/docker/certs.d/docker.io", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 77960] socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 25
# 创建文件描述符 25,用于 DNS 查询。
[pid 77960] setsockopt(25, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
# 向本地 DNS 服务器 127.0.0.53(通常是 systemd-resolved)发送查询请求,解析 index.docker.io。
[pid 77960] connect(25, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
[pid 77960] getsockname(25, {sa_family=AF_INET, sin_port=htons(58696), sin_addr=inet_addr("127.0.0.1")}, [112->16]) = 0
[pid 77960] getpeername(25, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, [112->16]) = 0
[pid 77960] read(25, 0xc000c7a000, 1232) = -1 EAGAIN (Resource temporarily unavailable)
[pid 77960] read(21, 0xc000bea071, 1)   = -1 EAGAIN (Resource temporarily unavailable)
[pid 77960] socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 29
[pid 77960] setsockopt(29, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
[pid 77960] connect(29, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
[pid 77960] getsockname(29, {sa_family=AF_INET, sin_port=htons(20314), sin_addr=inet_addr("127.0.0.1")}, [112->16]) = 0
[pid 77960] getpeername(29, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, [112->16]) = 0
[pid 77960] read(29, 0xc000c7aa00, 1232) = -1 EAGAIN (Resource temporarily unavailable)
[pid 77960] read(25, "_<\201\200\0\1\0\1\0\0\0\1\5index\6docker\2io\0\0\34\0\1\300\f\0\34\0\1\0\0\0\30\0\20*\3(\200\3611\0\203\372\316\260\f\0\0%\336\0\0)\377\326\0\0\0\0\0\0", 1232) = 72
[pid 77960] read(29, "\345\342\201\200\0\1\0\1\0\0\0\1\5index\6docker\2io\0\0\1\0\1\300\f\0\1\0\1\0\0\0?\0\4l\240\246\375\0\0)\377\326\0\0\0\0\0\0", 1232) = 60
[pid 77960] socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 25
[pid 77960] setsockopt(25, SOL_IPV6, IPV6_V6ONLY, [0], 4) = 0
[pid 77960] setsockopt(25, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
# Docker 尝试通过 IPv6 连接 index.docker.io(IP:2a03:2880:f131:83:face:b00c:0:25de),但因网络配置或防火墙限制,IPv6 不可达(ENETUNREACH),随后会回退到 IPv4。
[pid 77960] connect(25, {sa_family=AF_INET6, sin6_port=htons(53), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "2a03:2880:f131:83:face:b00c:0:25de", &sin6_addr), sin6_scope_id=0}, 28) = -1 ENETUNREACH (Network is unreachable)
[pid 77960] socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 25
[pid 77960] setsockopt(25, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
# 进程通过文件描述符 25(UDP 套接字)连接到 IP 为 108.160.166.253、端口 53(DNS 服务默认端口)的服务器,连接成功(返回 0)。
# 这是向 DNS 服务器发送域名解析请求(如解析 index.docker.io),108.160.166.253 是 Cloudflare 的公共 DNS 服务器之一。
[pid 77960] connect(25, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("108.160.166.253")}, 16) = 0
# 获取当前进程(客户端)的套接字信息:使用 IP 172.20.0.11、端口 10106(随机分配的临时端口),操作成功(返回 0)。
[pid 77960] getsockname(25, {sa_family=AF_INET, sin_port=htons(10106), sin_addr=inet_addr("172.20.0.11")}, [112->16]) = 0
# 获取对端(DNS 服务器)的套接字信息:IP 108.160.166.253、端口 53,操作成功(返回 0)。
[pid 77960] getpeername(25, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("108.160.166.253")}, [112->16]) = 0
# 创建一个新的 TCP 套接字(文件描述符 25),准备通过 TCP 连接到目标服务器(此处为 Docker Hub)。
[pid 77960] socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 25
# 通过新创建的 TCP 套接字(描述符 25)连接到 IP 108.160.166.253、端口 443(HTTPS 默认端口),返回 -1 EINPROGRESS。
[pid 77960] connect(25, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("108.160.166.253")}, 16) = -1 EINPROGRESS (Operation now in progress)
[pid 77960] socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 29
[pid 77960] setsockopt(29, SOL_IPV6, IPV6_V6ONLY, [0], 4) = 0
[pid 77960] --- SIGURG {si_signo=SIGURG, si_code=SI_TKILL, si_pid=77672, si_uid=0} ---
[pid 77960] connect(29, {sa_family=AF_INET6, sin6_port=htons(443), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "2a03:2880:f131:83:face:b00c:0:25de", &sin6_addr), sin6_scope_id=0}, 28) = -1 ENETUNREACH (Network is unreachable)
[pid 77960] read(21, "", 4096)          = 0
# 客户端读取到 EOF,关闭连接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1184265.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2026年十字传动轴市场,口碑厂家大盘点,球齿传动轴/联轴器/传动轴/球齿联轴器/齿式联轴器,十字传动轴企业推荐排行榜 - 品牌推荐师

在工业生产中,十字传动轴作为核心传动部件,直接影响机械设备的运行效率与稳定性。尤其在重型机械、矿山机械、汽车制造等领域,其承载扭矩、补偿角度及使用寿命等指标,直接关系到设备的安全性与作业效率。随着国内工…

Springboot小树立社工服务中心管理信息系统9mpe3(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能&#xff1a;案主,社工,服务信息,服务类型,招聘信息,招聘类型,服务订单,分配信息,服务内容,评价打分,退单信息,工资信息,活动支出,外界捐助,考勤信息开题报告内容一、研究背景与意义随着社会治理体系的不断完善&#xff0c;公众对社区服务的需求呈现多…

写这个方法的人真是个不折不扣的大SB_Ruoyi

用set去封装push操作. 浓浓的外包风. /*** 缓存List数据** @param key 缓存的键值* @param dataList 待缓存的List数据* @return 缓存的对象*/ public <T> long setCacheList(final String key, final List<T…

【dz-1015】基于STM32单片机智能鱼缸

摘要 在观赏鱼养殖领域&#xff0c;水质状态、水温稳定性及饲喂合理性对鱼类生存质量与健康状况起着决定性作用。传统鱼缸管理多依赖人工换水、经验控温及定时投喂&#xff0c;存在水质恶化预警滞后、水温波动大、饲喂不规律等问题&#xff0c;难以满足精细化养殖的严苛需求。…

强烈安利MBA必备AI论文软件TOP8

强烈安利MBA必备AI论文软件TOP8 2026年MBA必备AI论文软件测评&#xff1a;精准匹配学术需求 随着人工智能技术在学术领域的广泛应用&#xff0c;MBA学生在撰写论文过程中对高效、专业的工具需求日益增长。然而&#xff0c;面对市场上众多的AI写作软件&#xff0c;如何选择真正适…

【dz-1009】基于单片机的智能头盔设计

基于单片机的智能头盔设计 摘 要 针对传统头盔功能单一、缺乏安全保障的问题&#xff0c;本文设计了一款基于STM32F103C8T6单片机的智能头盔。该头盔主要由光敏电阻、MPU6050传感器、GPS模块、超声波传感器、按键、OLED显示屏以及通信模块构成。通过光敏电阻实时监测光照强度&…

【dz-1008】基于单片机的环境监测系统设计

摘要 随着人们对生活环境质量关注度的不断提升&#xff0c;对环境参数的精准监测与及时预警变得尤为重要。传统的环境监测方式多依赖人工采样和实验室分析&#xff0c;不仅耗时费力、响应滞后&#xff0c;还存在数据获取不及时、监测范围有限等问题&#xff0c;难以满足实时、…

Springboot手机销售管理系统4g5v5(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能&#xff1a;用户,商品分类,商品信息开题报告内容SpringBoot手机销售管理系统开题报告一、研究背景与意义1.1 传统手机销售管理的痛点随着智能手机市场竞争加剧&#xff0c;传统销售管理模式面临以下问题&#xff1a;库存管理低效&#xff1a;依赖人工…

软件测试常见面试题汇总(2026版)

一、常见的面试题汇总 1、你做了几年的测试、自动化测试&#xff0c;说一下 selenium 的原理是什么&#xff1f; 我做了五年的测试&#xff0c;1年的自动化测试&#xff1b; selenium 它是用 http 协议来连接 webdriver &#xff0c;客户端可以使用 Java 或者 Python 各种编…

高校推荐SPSS国产替代软件有哪些:32倍速提升(案例库) - 品牌排行榜

一、开篇 教育部《2024年高等教育数字化转型报告》显示,全国2000余所高校科研数据分析需求年增长率达37%,统计软件采购预算占信息化投入的18%。随着信创政策深化,SPSS等进口软件面临授权成本高、本地化服务弱、数据…

Python零基础玩AI艺术:印象派生成API调用指南

Python零基础玩AI艺术&#xff1a;印象派生成API调用指南 你是不是也曾经被“安装环境”、“配置依赖”、“版本冲突”这些技术术语劝退过&#xff1f;明明只是想让一张普通照片变成莫奈风格的油画&#xff0c;结果光是搭环境就花了三天&#xff0c;最后还报了一堆看不懂的错误…

【数据分享】上市公司高管风险偏好数据+dofile(2007-2024年)

而今天要限时免费分享的数据就是上市公司高管风险偏好数据dofile&#xff08;2007-2024年&#xff09; 数据介绍 数据概况 数据名称&#xff1a;上市公司高管风险偏好数据dofile&#xff08;2007-2024年&#xff09; 数据年份&#xff1a;2007-2024 年 数据范围&#xff1a…

男女初婚年龄延后的多维解析:从个人选择到社会转型

男女初婚年龄延后的多维解析&#xff1a;从个人选择到社会转型中国男女初婚年龄正呈现显著延后趋势&#xff0c;2020 年全国平均初婚年龄达28.67 岁&#xff0c;上海等一线城市更是超过30 岁&#xff08;男性 30.8 岁、女性 29.5 岁&#xff09;&#xff0c;较 10 年前推迟约 3…

【dz-1014】基于单片机的智能药箱

摘 要 日常生活中&#xff0c;按时服药对治疗和康复至关重要&#xff0c;特别是老年人或慢性病患者。但记忆力下降或生活忙碌常导致忘记服药或混淆药品。因此&#xff0c;设计一款智能多功能储药箱具有重要意义。 本设计以STM32F103C8T6单片机为控制合作&#xff0c;通过RTC获…

2025年度经济数据点评:稳中有进,向新向优收官“十四五”

2025年度经济数据点评&#xff1a;稳中有进&#xff0c;向新向优收官“十四五”2025年&#xff0c;在复杂严峻的国内外经济环境下&#xff0c;我国在党中央坚强领导下&#xff0c;深入贯彻新发展理念&#xff0c;实施积极有为的宏观政策&#xff0c;国民经济顶压前行、向新向优…

【dz-1010】基于单片机的药品生产车间环境监测

摘要 随着医药行业的严格规范&#xff0c;药品生产车间的环境参数对药品质量与生产安全至关重要。传统车间环境监测依赖人工巡检和手动记录&#xff0c;存在数据滞后、调控不及时、误差较大等问题&#xff0c;难以满足药品生产的高标准要求。 基于 STM32F103C8T6 单片机的药品…

更弱智的算法学习 day48

单调栈基础通常是一维数组&#xff0c;要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置&#xff0c;此时我们就要想到可以用单调栈了&#xff0c;时间复杂度为O(n)。739. 每日温度 构建一个栈&#xff0c;用来一次存储从大到小的元素&#xff08;栈底大&#…

Flux.1-dev创意变现:非商用的合法途径

Flux.1-dev创意变现&#xff1a;非商用的合法途径 你是不是也听说过 Flux.1-dev 这个强大的文生图AI模型&#xff1f;它生成的图像质量极高&#xff0c;细节丰富&#xff0c;人物面部、毛发、衣物纹理都清晰逼真&#xff0c;甚至能精准还原复杂提示词。更吸引人的是——它是开…

【dz-1011】酒窖存储环境监测与控制系统设计

摘要 在酒类存储领域&#xff0c;酒窖环境参数的稳定对酒品品质与存储安全起着决定性作用。传统酒窖环境管理多依赖人工检查和经验调控&#xff0c;存在数据记录不及时、环境波动难把控、异常响应滞后等问题&#xff0c;难以满足高品质酒类存储的严苛需求。 基于 STM32F103C8…

学生党福利:NewBie-image-Exp0.1云端体验,比买显卡省90%

学生党福利&#xff1a;NewBie-image-Exp0.1云端体验&#xff0c;比买显卡省90% 你是不是也和我一样&#xff0c;是计算机专业的学生&#xff0c;正想做一个AI绘画相关的课题&#xff0c;却被现实狠狠“教育”了一顿&#xff1f;实验室的GPU要排队申请&#xff0c;等轮到你可能…