Jenkins容器部署微服务时出现daemon socket、permission denied等问题(天机学堂)
前言首先我们看到Docker daemon socket、permission denied和/var/run/docker.sock这几个关键词时就应优先从Socket 挂载和用户组权限两个方向排查。一、问题背景在天机学堂项目中Jenkins 本身通过 Docker 容器运行。流水线需要执行以下操作获取已经构建好的微服务 JAR 包根据 Dockerfile 构建镜像删除旧容器启动新的微服务容器。前面的 JAR 包和 Dockerfile 复制正常cp ../tjxt-dev-build/tj-user/target/tj-user.jar ./app.jar cp ../tjxt-dev-build/Dockerfile ./Dockerfile但执行 Docker 命令时出现报错Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock最终 Jenkins 输出Stage deploy skipped due to earlier failure(s) ERROR: script returned exit code 1 Finished: FAILURE这说明 JAR 包复制已经成功真正失败的是Jenkins 容器中的jenkins用户没有权限访问宿主机的 Docker Daemon。二、运行环境本次问题的环境如下宿主机CentOS 7 虚拟机 容器运行时Docker Jenkins运行在 Docker 容器中 Jenkins 容器名jenkins 微服务容器名tj-user Docker Socket/var/run/docker.sock通过下面的命令可以确认 Jenkins 是容器化部署docker ps -a | grep jenkins输出类似ea613792a874 jenkins ... 18080-8080/tcpJenkins 工作目录也位于/var/jenkins_home/workspace/tj-user这同样说明 Jenkins 运行在容器中。三、Docker Socket 是什么Docker 命令本身并不直接创建容器。例如执行docker psDocker 客户端会通过下面的 Unix Socket 向 Docker Daemon 发送请求/var/run/docker.sock调用关系可以理解为Jenkins 流水线 ↓ docker 命令 ↓ /var/run/docker.sock ↓ 宿主机 Docker Daemon ↓ 构建镜像、启动容器因此Jenkins 想在宿主机上构建镜像和启动容器需要同时满足两个条件Jenkins 容器内存在docker命令Jenkins 用户有权限访问/var/run/docker.sock。本次环境中 Docker 命令已经存在真正缺少的是第二个条件。四、定位问题1. 检查宿主机 Docker Socket 权限在宿主机执行ls -ln /var/run/docker.sock本次输出srw-rw----. 1 0 994 0 Jul 29 22:53 /var/run/docker.sock这里使用了-n参数因此用户和组显示为数字 ID。各字段含义如下srw-rw---- │ │ │ │ │ └── 其他用户没有权限 │ └───── 所属组可以读写 └─────── 所有者可以读写Socket 的所有者信息为UID 0 GID 994还可以使用下面的命令进一步确认stat -c 权限%a UID%u GID%g /var/run/docker.sock输出权限660 UID0 GID994其中660表示所有者具有读写权限所属组具有读写权限其他用户没有任何权限。也就是说只有以下两类用户能够操作 Dockerroot 用户 GID 为 994 的用户组成员2. 检查 Jenkins 容器中的运行用户执行docker exec jenkins sh -c whoami; id; ls -ln /var/run/docker.sock本次输出jenkins uid1000(jenkins) gid1000(jenkins) groups1000(jenkins) srw-rw----. 1 0 994 0 Jul 29 14:53 /var/run/docker.sock可以得到以下信息Jenkins 用户 UID1000 Jenkins 主组 GID1000 Jenkins 所属组只有 1000 Docker Socket GID994Jenkins 用户既不是root也不属于 GID 为994的组。因此权限校验结果为Docker Socket 要求root 或 GID 994 Jenkins 当前身份UID 1000、GID 1000 结果无权访问这就是 Jenkins 流水线报错的根本原因。五、解决步骤步骤一查看容器内是否已经存在 GID 994 的组执行-v /var/run/docker.sock:/var/run/docker.sockdocker exec -u root jenkins getent group 994本次输出dockerhost:x:994:jenkins字段含义为dockerhost : 用户组名称 x : 组密码占位符 994 : 用户组 GID jenkins : 该组中的成员说明容器中已经存在一个名为dockerhost的组其 GID 正好为994。步骤二将 Jenkins 用户加入对应用户组假如查询结果中没有jenkins用户可以执行docker exec -u root jenkins usermod -aG dockerhost jenkins参数解释usermod用于修改用户属性。-a表示追加用户组而不是覆盖 Jenkins 原有的用户组。-G dockerhost表示将用户加入附加组dockerhost。jenkins表示需要修改的用户。这里必须使用-aG不建议只使用-G因为单独使用-G可能覆盖用户原有的附加组。如果容器内没有 GID 为994的组则需要先创建docker exec -u root jenkins groupadd -g 994 dockerhost然后再添加 Jenkins 用户docker exec -u root jenkins usermod -aG dockerhost jenkins其中groupadd -g 994 dockerhost表示创建一个名为dockerhost、GID 为994的用户组。这里关键的不是组名而是数字 GID 必须和宿主机 Docker Socket 的 GID 一致。步骤三重启 Jenkins 容器修改用户组后需要重启 Jenkins 容器docker restart jenkins原因是已经运行的 Jenkins Java 进程不会自动重新加载修改后的附加用户组。如果不重启即使/etc/group中已经出现 Jenkins 用户原 Jenkins 进程仍可能继续使用旧权限。重启后等待 Jenkins 完成启动docker ps | grep jenkins也可以查看日志docker logs --tail 100 jenkins步骤四验证 Jenkins 用户组执行docker exec jenkins id正常情况下应该看到类似结果uid1000(jenkins) gid1000(jenkins) groups1000(jenkins),994(dockerhost)重点检查是否出现994(dockerhost)出现该内容说明 Jenkins 用户已经成功加入 Docker Socket 对应的用户组。步骤五验证 Jenkins 是否能够操作 Docker执行docker exec -u jenkins jenkins docker ps该命令表示以 jenkins 用户身份 在 jenkins 容器中 执行 docker ps如果能够正常列出宿主机中的容器例如seata nacos xxljob gogs mq jenkins mysql nginx es redis并且不再出现permission denied就说明权限问题已经解决。最后回到 Jenkins 页面重新执行tj-user流水线即可。六、完整修复命令本次环境中Docker Socket 的 GID 为994完整操作如下# 1. 查看宿主机 Docker Socket 的权限和 GID ls -ln /var/run/docker.sock stat -c 权限%a UID%u GID%g /var/run/docker.sock # 2. 查看 Jenkins 用户和 Socket 权限 docker exec jenkins sh -c whoami; id; ls -ln /var/run/docker.sock # 3. 检查 Jenkins 容器内是否存在 GID 994 docker exec -u root jenkins getent group 994 # 4. 如果 dockerhost 组已经存在将 Jenkins 加入该组 docker exec -u root jenkins usermod -aG dockerhost jenkins # 5. 如果组不存在先创建再添加用户 docker exec -u root jenkins groupadd -g 994 dockerhost docker exec -u root jenkins usermod -aG dockerhost jenkins # 6. 重启 Jenkins 容器 docker restart jenkins # 7. 验证用户组 docker exec jenkins id # 8. 验证 Docker 操作权限 docker exec -u jenkins jenkins docker ps注意第四步和第五步根据实际查询结果二选一不要重复创建相同 GID 的用户组。七、为什么不能只在宿主机执行usermod有些教程会直接执行usermod -aG docker jenkins这种方式只适用于 Jenkins 直接安装在宿主机上的情况。本次 Jenkins 运行在 Docker 容器中宿主机用户系统 和 Jenkins 容器用户系统属于两个不同的用户空间。因此在宿主机修改jenkins用户组通常不会直接影响 Jenkins 容器内部的用户。正确做法是docker exec -u root jenkins ...进入 Jenkins 容器内部修改用户组。八、为什么用户组名称不同也可以访问宿主机中的 GID 994 可能对应docker而 Jenkins 容器中的 GID 994 可能对应dockerhost例如宿主机docker:x:994 容器内dockerhost:x:994:jenkins虽然组名不同但 Linux 做权限判断时主要比较的是数字 GID而不是组名。因此只要满足Socket 所属 GID Jenkins 附加组 GID就可以获得访问权限。本次环境中Socket GID 994 dockerhost GID 994两者一致所以 Jenkins 可以访问 Docker Socket。九、不推荐的临时解决方案网上常见的解决方法是chmod 666 /var/run/docker.sock该命令会将 Socket 权限修改为所有用户都可以读写虽然可能立即解决问题但不推荐长期使用。主要原因有两个。第一权限范围过大。任何能够访问该 Socket 的用户都可能操作宿主机 Docker包括启动特权容器 挂载宿主机目录 删除容器 删除镜像 读取宿主机文件第二Docker 服务重启后Socket 可能重新创建手动修改的权限可能失效。因此更合理的方案是保持 Docker Socket 权限为 660 让 Jenkins 用户加入对应 GID 的用户组十、需要同时检查 Docker Socket 是否挂载Jenkins 容器想控制宿主机 Docker还必须挂载 Docker Socket。可以执行docker inspect jenkins \ --format {{range .Mounts}}{{println .Source - .Destination}}{{end}}正常应该出现/var/run/docker.sock - /var/run/docker.sock如果没有该挂载即使用户组权限正确Jenkins 容器也无法访问宿主机 Docker。创建 Jenkins 容器时通常需要添加-v /var/run/docker.sock:/var/run/docker.sock例如docker run -d \ --name jenkins \ -p 18080:8080 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ jenkins/jenkins:lts其中-v /var/run/docker.sock:/var/run/docker.sock表示把宿主机 Docker Socket 映射到 Jenkins 容器中的相同位置。十一、需要注意容器重建问题通过下面的命令修改用户组docker exec -u root jenkins usermod -aG dockerhost jenkins修改的是当前 Jenkins 容器内部的文件系统。如果以后执行docker rm jenkins并重新创建 Jenkins 容器那么本次用户组修改可能丢失。更稳定的方式是在创建 Jenkins 容器时添加附加组。先查询宿主机 Docker Socket 的 GIDstat -c %g /var/run/docker.sock假设结果为994创建容器时可以添加--group-add 994示例docker run -d \ --name jenkins \ -p 18080:8080 \ --group-add 994 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ jenkins/jenkins:lts这样 Jenkins 容器启动时就会直接获得 GID 994 的附加组权限。如果使用 Docker Compose可以配置services: jenkins: image: jenkins/jenkins:lts container_name: jenkins ports: - 18080:8080 volumes: - jenkins-data:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock group_add: - 994这种方式比进入容器手动修改更加持久。十二、问题总结本次故障不是以下问题导致的JAR 包构建失败 Dockerfile 编写错误 Jenkinsfile 语法错误 微服务代码错误 Docker 服务没有启动真正原因是宿主机 Docker Socket 的 GID 为 994 Jenkins 容器用户只属于 GID 1000 Jenkins 无权读写 /var/run/docker.sock最终解决链路为查看 Docker Socket 权限 ↓ 确认 Socket GID 为 994 ↓ 查看 Jenkins 用户所属组 ↓ 发现 Jenkins 不属于 GID 994 ↓ 在容器内创建或使用 GID 994 的用户组 ↓ 将 Jenkins 用户加入该组 ↓ 重启 Jenkins 容器 ↓ 使用 Jenkins 用户执行 docker ps 验证 ↓ 重新运行流水线最终 Jenkins 流水线恢复执行docker ps docker images docker build docker rundeploy阶段也可以继续运行。十三、核心排查思路遇到同类报错permission denied while trying to connect to the Docker daemon socket不要立即修改 Jenkinsfile也不要直接重装 Jenkins。优先检查下面三项# Docker Socket 属于哪个 GID stat -c %g /var/run/docker.sock # Jenkins 当前属于哪些组 docker exec jenkins id # Jenkins 容器是否挂载 Docker Socket docker inspect jenkins \ --format {{range .Mounts}}{{println .Source - .Destination}}{{end}}只要保证Docker Socket 已正确挂载 Jenkins 容器内存在 docker 命令 Jenkins 用户所属组包含 Socket 的 GIDJenkins 就能够正常调用宿主机 Docker。

相关新闻

8月技术展望:AI后端架构师的下一个月重点方向与学习计划

8月技术展望:AI后端架构师的下一个月重点方向与学习计划

8月技术展望:AI后端架构师的下一个月重点方向与学习计划 站在7月最后一天往回看,30篇文章覆盖了AI后端、高可用架构、性能调优、分布式系统、云原生五个技术领域。站在这个基础上往8月看,哪些方向会加速?哪些能力值得投入时间&…

2026/10/18 0:28:06 阅读更多 →
2024金融机构数据安全合规建设与关键技术解析

2024金融机构数据安全合规建设与关键技术解析

1. 2024金融机构数据安全合规建设全景扫描金融行业正面临前所未有的数据安全挑战。根据我们团队对全国37家商业银行、12家证券公司和8家保险机构的实地调研,2023年金融机构数据泄露事件同比激增42%,其中83%的案例涉及客户敏感信息。这个数字背后反映的是…

2026/10/17 12:04:00 阅读更多 →
Nacos注册中心:服务注册、发现、健康检测

Nacos注册中心:服务注册、发现、健康检测

Nacos注册中心:服务注册、发现、健康检测 微服务世界里,服务之间打招呼的方式不是"你好",而是"你在哪?你的 IP 是多少?"——这就是注册中心干的事。 一、注册中心到底解决什么问题? 单…

2026/10/17 14:57:02 阅读更多 →

最新新闻

低代码开发实战:用Oracle APEX把一张表变成可交付的Web系统

低代码开发实战:用Oracle APEX把一张表变成可交付的Web系统

简介:Oracle APEX(Application Express)是Oracle官方推出的低代码Web开发平台,用于在浏览器中快速构建企业级数据库应用。《Oracle APEX深入浅出》面向Oracle数据库开发人员、APEX初学者及有Web应用开发需求的工程师,围…

2026/10/18 0:28:16 阅读更多 →
科大讯飞AstronClaw到底怎么样?从OpenClaw到AI智能体的技术底座与落地路径全解析

科大讯飞AstronClaw到底怎么样?从OpenClaw到AI智能体的技术底座与落地路径全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:28:16 阅读更多 →
还在手动转录m4a音频浪费时间?用TaoToken统一Key打通4款m4a转文字在线工具,3分钟搞定2小时录音

还在手动转录m4a音频浪费时间?用TaoToken统一Key打通4款m4a转文字在线工具,3分钟搞定2小时录音

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:28:16 阅读更多 →
WSL2 本地化部署 ChatGLM2+FastGPT+oneapi 接入 TaoToken 统一 Key 通道

WSL2 本地化部署 ChatGLM2+FastGPT+oneapi 接入 TaoToken 统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:28:16 阅读更多 →
Cursor终端中文乱码排查:把Base URL改到TaoToken后编码异常的定位与修复

Cursor终端中文乱码排查:把Base URL改到TaoToken后编码异常的定位与修复

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:28:16 阅读更多 →
2022数模B题无人机纯方位无源定位:MATLAB代码复现与避坑指南

2022数模B题无人机纯方位无源定位:MATLAB代码复现与避坑指南

简介:本资源为2022年全国大学生数学建模竞赛本科组B题的完整论文PDF,聚焦无人机纯方位无源定位问题,适合备战数模竞赛的本科生及指导教师参考。论文围绕圆形与锥形两种编队,系统建立被动接收信号无人机的定位模型与位置调整模型&a…

2026/10/18 0:27:15 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →