无法访问Docker守护进程套接字unix:///var/run/docker.sock的权限。

13

我有这个Dockerfile

FROM chekote/gulp:latest 

USER root
RUN apt-get update \
      && apt-get upgrade -y \
      && apt-get install -y sudo libltdl-dev

ARG dockerUser='my-user-name';
ARG group='docker';

# crate group if not exists
 RUN if ! grep -q -E "^$group:" /etc/group; then groupadd $group; fi

# create user if not exists
 RUN if ! grep -q -E "^$dockerUser:" /etc/passwd; then useradd -c 'Docker image creator' -m -s '/bin/bash' -g $group $dockerUser; fi

# add user to the group (if it was present and not created at the line above)
 RUN usermod -a -G ${group} ${dockerUser}

# set default user that runs the container
 USER ${dockerUser}

我是这样构建的:

docker build --tag my-gulp:latest .

最后通过script这种方式运行:

#!/bin/bash

image="my-gulp:latest";
workDir='/home/gulp/project';

docker run -it --rm  \
-v $(pwd):${workDir} \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
${image} /bin/bash

通过这个命令我成功登录到 Docker 容器,但是当我想查看镜像时就遇到了问题。

docker images

或尝试拉取镜像

docker pull hello-world:latest

我遇到了这个错误:

试图连接到unix:///var/run/docker.sock的Docker守护程序套接字时,遇到了权限被拒绝的错误: 在http://%2Fvar%2Frun%2Fdocker.sock/v1.38/images/json上获取:拨号unix / var / run / docker.sock时:连接:权限被拒绝

如何从chekote/gulp:latest创建docker镜像,以便我可以在其中使用docker而不会出现错误?

或者,错误是因为错误的docker运行命令导致的吗?


1
我不是100%确定,但在运行容器时尝试使用“--privileged”标记。这可能会起作用。 - scipsycho
为什么你要试图在你的Docker容器中进行Inception? - Codebling
3
@Code Bling,这不是“盗梦空间”,gulp容器内部不运行docker的容器,而是使用主机的docker启动其他与gulp容器同级别的docker容器。docker命令从gulp容器向外传递到运行其他容器的主机,在主机的角度看,这与通过未被容器化的gulp运行容器类似。原因在于:即使主机上没有安装gulp,您也可以轻松地通过使用不同的容器(例如3.x和4.x)之间切换gulp版本。 - Jimmix
1
@Jimmix 哦,很不错!但是......盗梦空间。 - Codebling
5个回答

58
快速避免此问题的方法是将您的用户添加到该组中。
sudo gpasswd -a $USER docker

然后设置适当的权限。

sudo setfacl -m "user:$USER:rw" /var/run/docker.sock

从那里开始应该会很好。


2
Docker文档也详细说明了这一点: https://docs.docker.com/engine/install/linux-postinstall/ - Stephen

15

权限匹配仅在数字用户ID和组ID上进行。如果套接字文件的模式为0660,所有者为用户ID 0和组ID 32,并且您以用户ID 1000和组ID 1000和16的身份调用它,则无论一个/etc/group文件将gid 32命名为docker,另一个将gid 16命名为相同的名称,都没有关系;数字gids是不同的,因此您无法访问该文件。此外,由于Docker组的实际数字gid会因系统而异,因此这不是您可以嵌入Dockerfile中的内容。

许多Docker镜像只作为root运行;如果是这样,它们可以访问绑定挂载的Docker套接字文件,而不管其权限如何。

如果您作为非root用户运行,则可以使用docker run --group-add选项将(数字)gid添加到有效用户;它不需要在/etc/groups文件中特别提到。在Linux主机上,您可能会运行:

docker run --group-add $(stat -c '%g' /var/run/docker.sock) ...

通常情况下,您不会在Dockerfile中安装sudo(它对于非交互式程序效果不佳,由于容器的短暂性质,通常不会在交互式shell中执行太多操作,您始终可以使用docker exec -u 0获取root shell),尽管安装一些非root用户通常被认为是最佳实践。您可以将Dockerfile简化为以下内容:

FROM node:8
RUN apt-get update
# Trying to use the host's `docker` binary may not work well
RUN apt-get install -y docker.io
# Install the single node tool you need
RUN npm install -g gulp
# Get your non-root user
RUN adduser myusername
# Normal Dockerfile bits
WORKDIR ...
COPY ...
RUN gulp
USER myusername
CMD ["npm", "run", "start"]

(Docker基础镜像存在一些 问题 不符合 Docker最佳实践, 而且似乎没有定期更新; 我建议使用标准的node镜像作为基础, 然后在其上添加所需的构建工具.)


你能详细说明一下这个语句“尝试使用主机的Docker二进制文件可能不会很好地工作”吗?我在许多地方挂载Docker二进制文件以避免安装Docker。 - Sairam Krish
主机是MacOS,但容器是Linux,所以主机的docker二进制文件无法工作。主机和容器都是Linux,但共享库依赖项不同。Docker镜像的一个关键目标是使其完全自包含,从主机注入二进制文件或代码会违反这个规则。 - David Maze
我同意你的观点,注入二进制文件并不好。在Docker的情况下,我使用Docker外部的Docker(DooS),当我将MacOS Docker二进制文件挂载到Linux容器时,它可以正常工作而没有问题。我相信,如果主机是Windows,可能无法正常工作。但是,您是否认为在Linux容器上挂载MacOS Docker二进制文件存在任何问题?这有助于避免在容器镜像中安装Docker。 - Sairam Krish
一个MacOS二进制文件在Linux环境中是无法运行的,这是不言而喻的。依赖于从主机注入代码的图像也不会具备可移植性,这就违背了使用Docker的初衷。 - David Maze
非常感谢您,特别是group-add标志。它使我免于进行一些hack来实现其等效功能。 - Lokesh

6

打开终端并输入以下命令

sudo chmod 666 /var/run/docker.sock

请告诉我结果...


1
谢谢@Mohit Rakhade,对我很有帮助。 - Omar Merghany
1
最简单的答案。 - PAT-O-MATION
最好和容易!! - ASB
很抱歉,但这是一个糟糕的答案。它打开了Docker套接字,使任何人都可以写入。我只会考虑在我的本地开发机器上使用它 - 即使在那里,这也是一个糟糕的做法。如果图像应该在除本地环境之外的任何地方工作,那么应该尽一切可能避免这种情况。 - Tomasz Struczyński

0
错误与docker pull或docker image子命令无关,而是您需要将docker命令作为具有对docker套接字的写访问权限的用户之一调用(例如,通过root,使用sudo或通过在docker组中)。

但我在Dockerfile中将'my-user-name'添加到'docker'组了,不是吗? RUN usermod -a -G ${group} ${dockerUser} - Jimmix
你需要将主机上的用户添加到docker组中,而不是容器中的用户。Dockerfile的RUN命令在容器内运行,无法影响主机。 - Lie Ryan

0

该图像描述的第一行是:“通常不建议在Docker内部运行Docker”。您无需使用--privileged即可访问绑定挂载的主机Docker套接字,只需正确设置套接字文件的Unix权限即可。 - David Maze
@DavidMaze 是的,这在生产环境中并不推荐,但他仍然想尝试,可能只是为了测试,通过制作自己的 dind 来实现,这是多余的。 - Ijaz Ahmad

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