如何解决Docker的权限错误?


如何解决Docker的权限错误:“尝试连接到 Docker 守护程序套接字时权限被拒绝Permission Denied While Trying to Connect to the Docker Daemon Socket”?

由于其众多优势,容器已成为 IT 行业的技术流行语。Docker平台是最著名和最常用的容器平台,拥有相当大的开发人员社区。

权限错误是访问软件时在软件上下文中处理的最常见问题。

在本教程中,我们将探讨此错误的原因并提供修复它的解决方案,包括使用sudo和将用户添加到 Docker 组。

Docker Engine 是一个完整的容器运行时环境,包括 Docker CLI、Docker API 和 Docker 守护进程。此外,Docker 守护进程是在主机上运行的后台进程;它接收来自 Docker CLI 或客户端的请求,并连接到 Docker API 以管理 Docker 容器、镜像、卷、网络和其他 Docker 对象。

此外,它使用 Unix 网络套接字在 Docker 客户端和守护进程之间进行通信:

$ docker run ubuntu:latest /bin/bash
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.

每当用户没有适当的 Docker 守护程序套接字访问权限时,客户端总是会遇到“尝试连接到 Docker 守护程序套接字时权限被拒绝”错误。

接下来,让我们看看如何解决这个问题。

将/var/run/docker.sock的权限更改为 ' 666 ' 是危险的
默认情况下,只有root和docker用户组成员可以访问 Docker 套接字:

$ ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 May 13 06:05 /var/run/docker.sock

我们中的一些人可能想出一个简单的“解决方案”——使用chmod命令修改sock文件的权限,以便任何用户都可以读写套接字:

$ sudo chmod 666 /var/run/docker.sock

$ ls -l /var/run/docker.sock
srw-rw-rw- 1 root docker 0 Mar 13 06:05 /var/run/docker.sock

重启Docker服务后,任何用户都可以管理Docker镜像和启动容器。这确实避免了“权限被拒绝”的问题:

$ systemctl restart docker.service

$ docker run -it ubuntu:latest /bin/bash
root@fa679b3875fe:/#

我们可能认为用户启动一个 Docker 容器很方便。
但是,这种权限更改具有潜在的危险。
一个例子可以快速解释它:

假设我们的系统中有一个用户baeldunguser。现在,让我们启动Ubuntu容器并将主机的根 ( / ) 目录挂载为/host 卷:

baeldunguser$ docker run -it -v /:/host ubuntu:latest /bin/bash
root@fa679b3875fe:/#

如上面的输出所示,我们已经成功进入容器的 shell。

现在,让我们对/host目录进行一些更改,例如,创建一个文件:

root@fa679b3875fe:/# touch /host/changed-by-docker-container.hello

然后,如果我们检查主机,我们可以看到文件是在根 ( / ) 目录中创建的:

baeldunguser$ ls -l /changed-by-docker-container.hello
-rw-r--r-- 1 root root 0 Jun  3 20:38 /changed-by-docker-container.hello

但是,只允许root用户写入根 ( / ) 目录:

baeldunguser$ ls -ld /
drwxr-xr-x 19 root root 4096 Jun  3 20:38 /

当然,我们不想破坏主机上的系统。因此,我们创建了一个文件作为示例。

但是我们已经意识到 baeldunguser用户有可能通过 Docker 容器对主机系统造成重大损害

因此,我们不应该允许任何人读写 Docker 套接字守护进程

接下来,让我们看看权限问题的正确解决方案。

解决Docker和用户权限的权限错误
有多种方法可以解决此权限问题。让我们从解决这个问题的临时解决方案开始。作为快速修复,我们可以在 Linux 中使用sudo(superuser do)命令来提升用户的特权或权限。它将进一步帮助我们毫无问题地运行 Docker 命令:

$ sudo docker run -it ubuntu:latest /bin/bash
[sudo] password for baeldunguser:
root@5a909c4c6138:/#

现在,按照以下步骤永久解决访问 Docker daemon socket 的权限问题。

1、首先,检查 Docker 用户组是否在主机上可用。如果没有,我们可以使用groupadd命令添加它:

$ sudo groupadd docker

$ getent group docker
docker:x:999:

$ awk -F':' '/docker/{print $4}' /etc/group

2、接下来,让我们将用户添加到 Docker 组,该组授予对 Docker 守护程序套接字的必要访问权限:

$ sudo usermod -aG docker baeldunguser

为了使更改生效,我们必须注销之前的会话,并在将用户添加到docker组后重新进入新会话:

$ getent group docker
docker:x:999:baeldunguser

$ awk -F':' '/docker/{print $4}' /etc/group
baeldunguser

3、最后,通过使用systemctl restart docker.service命令重新启动 Docker 守护进程服务来应用配置更改 :

$ sudo systemctl restart docker.service
$ sudo systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2023-03-13 07:23:16 IST; 2s ago
     Docs: https://docs.docker.com
 Main PID: 10196 (dockerd)
    Tasks: 13
   CGroup: /system.slice/docker.service
           └─10196 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

现在,我们已经使用适当的权限从baeldunguser用户空间成功执行了 Docker 命令:

$ docker run -it ubuntu:latest /bin/bash
root@fa679b3875fe:/#

结论
解决办法是:将用户永久添加到适当的组中。

总体而言,通过遵循最佳部署实践,用户可以避免此类常见错误并确保其 Docker 环境的平稳运行。