Docker内部容器权限错误

23

我在使用Docker作为CI的环境,基本上机器上有一个Jenkins CI服务器,并且使用相同的机器Docker套接字来创建用于CI的节点。

这一直很好地工作,直到最近我更新了Docker。我已经确定了问题,但似乎无法找到正确的方法来使其正常工作。

host $ docker exec -it myjenkins bash
jenkins@container $ docker ps
Got permission denied while trying to connect to the Docker daemon 
socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/containers/json: dial unix /var/run/docker.sock: connect: permission denied

host $ docker exec -it -u root -it myjenkins bash
root@container $ docker ps 
... docker ps from host container yay! ...

这是我的推测。我可以从容器内访问主机的docker套接字,但似乎无法授予jenkins用户权限。

我已经添加了docker组,并将jenkins用户添加到了docker组中。但仍然收到相同的错误。我已经重新启动了很多次,所以不太确定下一步该怎么做。

有没有一种方法可以强制为特定套接字上的用户授予权限?


只是出于好奇,您是否尝试使用特权容器(作为内部的根用户)尝试了同样的事情? - Nehal J Wani
如果您查看我的问题,我展示了控制台。我展示了我尝试使用jenkins用户和容器的root用户。root用户有访问权限,而jenkins用户没有。 - Brandon Bertelsen
只是出于好奇,您是否尝试过在特权容器中执行相同的操作(如jenkins内部)? - Nehal J Wani
使用 --userns=host 也是同样的情况吗? - Nehal J Wani
这是一个特权容器。我不确定如何使用 --userns=host,您可以告诉我如何在 docker-compose 中指定它吗? - Brandon Bertelsen
4个回答

32

您需要将宿主机上Docker组的gid映射到容器内Jenkins所属组的gid。以下是我在Dockerfile中构建Jenkins从节点镜像的示例:

ARG DOCKER_GID=993

RUN groupadd -g ${DOCKER_GID} docker \
  && curl -sSL https://get.docker.com/ | sh \
  && apt-get -q autoremove \
  && apt-get -q clean -y \
  && rm -rf /var/lib/apt/lists/* /var/cache/apt/*.bin 

RUN useradd -m -d /home/jenkins -s /bin/sh jenkins \
  && usermod -aG docker jenkins

在这个例子中,993恰好是主机上docker的gid,您需要根据自己的环境进行调整。


原帖作者的解决方案: 如果无法重新构建,则可以在使用root和添加用户时相应地设置docker组。如果您之前尝试过此操作,则可能需要在从属节点上删除该组(groupdel docker):

docker exec -it -u root myjenkins bash
container $ groupadd -g 993 docker
container $ usermod -aG docker jenkins

好的,我明白了。在主机上docker是999,在从机上docker是1001。所以你的意思是我需要确保从机上的gid与主机上相同?你认为我只需编辑/etc/group就可以了吗? - Brandon Bertelsen
1
docker.sock 文件的 gid 需要是容器内用户的 gid。您可以在映像中创建任何具有此 id 的组,并将 Jenkins 添加到该组中。更改主机上的 /etc/group 是不起作用的,除非还修复文件的权限。 - BMitch
1
非常好,非常好,非常好。我将使用我的修复更新您的答案。 - Brandon Bertelsen
1
@BMitch,您真是一位Docker大师。太棒了!我已经为这个问题奋斗了三个多小时了。最终,您的答案解决了我的问题 :-) - Bilal Usean
当我将docker.sock挂载到容器时,ls -l显示为nobody nogroup。我错过了什么? - Ali Yeşilkanat
主机上的UID/GID是多少?容器中的UID/GID又是多少?您是否配置了用户命名空间? - BMitch

4

如其他答案中提到的那样,您必须确保容器内的用户"jenkins"有权限通过/var/run/docker.sock挂载点向主机上的Docker引擎发出Docker命令。

一个简单的方法是:

$ docker run --rm -d --group-add $(stat -c '%g' /var/run/docker.sock) -v /var/run/docker.sock:/var/run/docker.sock -P myjenkins

但是要注意:

如果您的Jenkins任务需要执行Docker构建/运行命令(例如构建容器),那么这是不够的。原因是容器化的Jenkins将要求主机中的Docker部署Docker代理容器,而该Docker代理容器在连接到主机上的Docker守护程序时也会面临类似的“权限错误”。

有一篇博客文章描述了此问题和解决方案,位于https://blog.nestybox.com/2019/09/29/jenkins.html


1
个人而言,我刚刚不得不做这件事:

sudo gpasswd -a $USER docker 

它成功了


0

通过在开头包含sudo,使用您的root用户执行命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接