如何在不使用sudo的情况下使用Docker?

在Docker的文档页面上,所有示例命令都没有显示sudo,就像这个例子一样:
docker ps

在Ubuntu上,二进制文件被称为docker.io。它也不能在没有sudo的情况下工作。
sudo docker.io ps

如何配置Docker,以便我不需要在每个Docker命令前加上“sudo”?

2别忘了启用ufw ;) - Rinzwind
2在Ubuntu 14.04上,还有一个名为'docker'的二进制文件。 - anatoly techtonik
@anatolytechtonik 我在Ubuntu 14.04 LTS中也使用了'docker'而不是'docker.io'。 - Nabin
2推荐的安装方式不是使用默认的Ubuntu软件仓库中的Docker,而是建议按照此处的说明(https://docs.docker.com/engine/installation/linux/ubuntulinux/)使用Docker仓库。请删除所有现有的Docker相关内容,并确保您从正确的来源获取:`apt-cache policy docker-engine`(apt的URL应该来自dockerproject.org)。 - michael
4怎么样使用一个别名呢?这样你仍然可以使用sudo,并且有密码保护。别名docker="sudo docker" - Andrej Panjkov
是的,直到Docker实施policykit或类似的东西之前,我强烈建议使用别名,否则你可能就得以root用户身份运行所有东西了。 - Jonathan Baldwin
sudo chmod 666 /var/run/docker.sock - Keutelvocht
1需要root权限才能执行docker info这样简单的任务,这是什么垃圾?就像docker info需要访问我所有的文件、设备和端口一样。 - Rolf
@Flimm 你的标志说“这可能是一个错误的答案”。如果是一个错误的答案,那么你应该直接标记评论以便删除。 - Thomas Ward
@TechnicalKeera,这样做会有一些问题,因为Docker守护进程无法与套接字通信。此外,这个解决方案也不会持久生效,因为在下次启动时会以不同的用户重新创建。如果你想要绕过sudo来使用docker,你应该将你的用户添加到docker组中,以获得用户的无限制执行权限 - 不过这样做存在安全风险,所以在需要以管理员身份运行的情况下,你应该使用sudo来处理相关命令。 - Thomas Ward
5个回答

好消息:新的Docker版本19.03(目前处于实验阶段)将能够以非root用户身份运行,消除了使用root用户可能出现的问题。不再需要处理提升权限、root用户和任何可能在你不想要的时候打开你的机器的东西。
关于此事的视频来自[DockerCon 2019] 使用Rootless模式加固Docker守护程序

关于非root用户Docker模式的一些注意事项

Docker工程师表示,非root用户模式不能被视为完整的Docker引擎功能套件的替代品。非root用户模式的一些限制包括:

  • cgroups资源控制、apparmor安全配置文件、检查点/恢复、覆盖网络等在非root用户模式下无法工作。
  • 从容器中暴露端口目前需要手动进行socat辅助进程。
  • 只有基于Ubuntu的发行版支持非root用户模式下的覆盖文件系统。
  • 非root用户模式目前仅适用于可能不像您习惯的那样稳定的夜间构建版本。

截至Docker 19.3版本,这已经过时(而且比必要的更危险):
关于此,Docker手册有以下说明:

Giving non-root access

The docker daemon always runs as the root user, and since Docker version 0.5.2, the docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root, and so, by default, you can access it with sudo.

Starting in version 0.5.3, if you (or your Docker installer) create a Unix group called docker and add users to it, then the docker daemon will make the ownership of the Unix socket read/writable by the docker group when the daemon starts. The docker daemon must always run as the root user, but if you run the docker client as a user in the docker group then you don't need to add sudo to all the client commands. As of 0.9.0, you can specify that a group other than docker should own the Unix socket with the -G option.

Warning: The docker group (or the group specified with -G) is root-equivalent; see Docker Daemon Attack Surface details and this blogpost on Why we don't let non-root users run Docker in CentOS, Fedora, or RHEL (thanks michael-n).

In the recent release of the experimental rootless mode on GitHub, engineers mention rootless mode allows running dockerd as an unprivileged user, using user_namespaces(7), mount_namespaces(7), network_namespaces(7).

Users need to run dockerd-rootless.sh instead of dockerd.

$ dockerd-rootless.sh --experimental

As Rootless mode is experimental, users need to always run dockerd-rootless.sh with –experimental.


重要阅读:Linux的安装后步骤(它还链接到Docker Daemon攻击表面细节)。

以非root用户身份管理Docker

Docker守护进程绑定到Unix套接字而不是TCP端口。默认情况下,该Unix套接字由root用户拥有,其他用户只能使用sudo访问它。Docker守护进程始终以root用户身份运行。

如果您在使用docker命令时不想使用sudo,请创建一个名为docker的Unix组,并将用户添加到其中。当docker守护进程启动时,它会使Unix套接字的所有权可被docker组读写。


  • 如果docker组不存在,请添加:

    sudo groupadd docker
    
  • 将当前用户"$USER"添加到docker组中。如果您不想使用当前用户,请更改用户名以匹配您的首选用户:

    sudo gpasswd -a $USER docker
    
  • 要激活对组的更改,可以执行newgrp docker或注销/重新登录。

  • 您可以使用以下命令检查是否可以在没有sudo的情况下运行Docker:

    docker run hello-world
    

“您需要注销并重新登录以使更改生效。”这个提示已经存在一年多了? - Rinzwind
@Rinzwind,你能考虑一下这可能对主机系统产生的几个安全影响,并在回答中加以说明吗? - Lucio
2这难道不是最不安全的生产架构吗?我一定是漏掉了什么东西。 - matanster
@matt 并不是“最”不安全的。点击链接查看一些相关内容:“首先,只有可信用户才应被允许控制您的Docker守护程序。”如果您将其与Web服务器(例如作为API)一起使用,则会增加另一层问题。 - Rinzwind
5是的,但每个特权进程都会带来潜在的漏洞利用可能性。Docker是否深入操作系统以确保这种特权级别? - matanster
4newgrp docker 对我来说没有起作用,我不得不退出登录。 - lolmaus - Andrey Mikhaylov
66值得指出的是,这使得用户具有无限制、非密码保护的根访问权限。请参阅此处的漏洞详情 - Chris Foster
1@ChrisFoster 这就是为什么里面有一个很大的警告。但是它也被设置成如果有人能够利用这个,那他们会遇到更大的问题;-) - Rinzwind
这个:“如果你使用的是Ubuntu 14.04及以上版本,请使用docker.io代替:sudo service docker.io restart”对于Ubuntu 16.04服务器版来说是不正确的。服务的名称只是叫做“docker”。不过,你可以通过Xenials普通的apt源使用sudo apt-get install docker.io来安装docker。 - Olof Bjarnason
3您无需重新启动Docker守护程序即可使此更改生效!只需让您刚刚添加的用户注销然后重新登录即可。 - Tommy
1有关这个“解决方案”所带来的安全漏洞的更多信息,请参阅:https://www.projectatomic.io/blog/2015/08/why-we-dont-let-non-root-users-run-docker-in-centos-fedora-or-rhel/ - michael
1@Tommy 这对我也起作用了,但我怀疑是因为docker组已经存在。如果在启动服务器之前docker组不存在,我敢打赌你必须重新启动它,或者至少执行systemctl reload docker命令。 - jpaugh
请注意,重新启动Docker服务将停止所有正在运行的容器。回想起来是显而易见的,但还是值得提醒大家。 - Aaron
正如@Tommy所说,不需要重新启动docker服务。Docker服务并不关心用户,它只接收匿名的HTTP请求来执行操作。将用户添加到docker组允许通过Unix套接字访问,从而进行请求。这完全是在客户端上进行的,不会主动运行,并且不受service docker restart的影响。 - Pijusn
@Pijusn已经将其删除。 - Rinzwind
7如果你使用docker login命令,你可能会发现在你的主文件夹中创建的.docker文件夹属于root用户。因此,在运行docker命令时,你会遇到以下警告:WARNING: Error loading config file:/home/myuser/.docker/config.json - stat /home/myuser/.docker/config.json: permission denied。为了让我的用户能够在没有sudo权限的情况下访问.docker文件夹,我执行了以下命令:sudo chgrp -hR docker ~/.docker && sudo chown -R myuser ~/.docker。然而,chgrp命令似乎没有起作用,所以我建议只执行chown步骤。 - Birchlabs
3@Tommy,我也不得不重新启动Docker服务器。由于我的docker组不存在,/var/run/docker.sock文件的所有权是root:root。当我重新启动Docker服务器时,它变成了root:docker。然后它对我起作用了。 - Greg
这个方法很有帮助,但关键是要运行@Christian Hujer写的sudo setfacl -m user:username:rw /var/run/docker.sock。 - Ben Yitzhaki
@BenYitzhaki 我并不想抢走他的一部分;-) - Rinzwind
@Rinzwind 没有真正关注评论,只是在这上面浪费了太多时间,当答案就在我面前时 :( - Ben Yitzhaki
按照提到的所有步骤进行操作,多次退出并重新登录,但没有起到作用。最后执行了"sudo service docker restart"命令,终于成功地在无需使用sudo的情况下运行docker镜像! - Bharat Mallapur
15我不得不重新启动Ubuntu。退出登录没有起作用。 - Philip Rego
你是在说现在我默认情况下不应该再遇到Got permission denied while trying...错误了吗?我仍然在Docker version 20.10.2, build 20.10.2-0ubuntu1~20.04.2上遇到这个错误,并且我仍然需要通过groupadd过程来解决它。 - Kvothe
sudo chown $USER /var/run/docker.sock 对我来说有效 - Tanjin Alam
@TanjinAlam 我建议在套接字具有组权限6(rw)时也包括群组(即$USER:$USER),如果低于它则无所谓。 - Rinzwind

要在不使用sudo的情况下运行docker命令,您需要将具有root权限的用户添加到docker组中。为此,请运行以下命令:
 sudo usermod -aG docker $USER

现在,让用户注销然后重新登录。这个解决方案在这里有详细的说明和正确的安装过程。

40将用户添加到组后,运行以下命令:sg 组名 -c "bash" - madjardi
8您不需要重新启动操作系统来使此更改生效!那样会导致所有正在运行的容器崩溃!只需让您刚添加的用户退出然后重新登录即可。 - Tommy
2这确实是官方Docker文档建议的做法,以便能够使用非特权用户运行Docker。 - Pejvan
8那个命令与其他答案中的 "sudo gpasswd -a ${USER} docker" 有什么不同?如果有的话... - Ashley Aitken
29请您能否添加文档中提供的警告:“docker组[...]等同于root”,这样人们就有机会考虑一下。 - Murmel
9与两年前的接受答案具有相同的效果,但没有关于安全风险的警告。 - Gert van den Berg
1仍然出现错误:在尝试连接到Docker守护程序套接字时,遇到了权限被拒绝的问题。请检查是否有足够的权限访问位于unix:///var/run/docker.sock的套接字。如果出现问题,请确保具备适当的权限以连接到/var/run/docker.sock,并执行所需的操作。 - Soren
2@Soren 经常退出登录无法生效,请重新启动机器并再次尝试。可以将这个信息更新到答案中。 - Snackoverflow
1需要重新启动 - Chang Zhao
2退出/登录没有起作用。我尝试了3次,但都没有成功。只有在系统重启后,才能正常工作。Ubuntu 22.04 LTS。请将答案更改为需要重新启动系统。 - Damn Vegetables
我不知道为什么人们还在使用带选项的usermod/useradd,而不是使用友好且方便的前端工具adduser $USER docker,这正是Debian推荐的方式。 - Pablo Bianchi

将用户添加到组docker的机制是获取对位于/var/run/docker.sock的docker套接字的访问权限。如果包含/var/run的文件系统已启用ACL,则还可以通过ACL实现此目的。
sudo setfacl -m user:$USER:rw /var/run/docker.sock

我只是为了完整性而包括这个。
一般来说,我建议尽量避免使用ACL,如果有基于组的良好替代方案可用的话:通过查看组成员身份来理解系统特权会更好。为了理解系统特权,必须扫描文件系统以获取ACL条目,这对安全审计来说是额外的负担。
警告1:这与将$USER添加到docker组具有相同的root等效性。您仍然可以以能够访问主机文件系统的root权限启动容器。
警告2:与基于组的安全相比,ACL在安全审计方面要困难得多。在可能的情况下,如果可以使用组来代替,请尽量避免使用ACL,至少在与审计相关的环境中如此。

10它在16.04上运行成功了。 - edib
2在我看来,这是一个好得多的方式。docker组等效于root,这总是一个危险的迹象。而且,我没有看到拥有这个文件有任何不利之处。 - xeruf
你能描述一下应该执行哪些命令来“获取对位于/var/run/docker.sock的Docker套接字的访问权限”吗? - Yuval Atzmon
@yuval 这个命令已经在答案中描述了,它是setfacl命令。 - Christian Hujer
11@Xerus 如果我理解正确的话,任何人可以写入此套接字,也可以获得等同于 root 的特权。因此,通过 ACL 给予某人对此套接字的访问权限与将该人员添加到 docker 组具有相同的安全效果。 - Paŭlo Ebermann
1这个解决方案也适用于Ubuntu 18.04。在此之前,我执行了sudo groupadd docker和sudo usermod -aG docker $USER的命令。 - loretoparisi
2请在Ubuntu 20.04上为我完成这项工作。 - Alexey Muravyov
在Ubuntu 21.04上工作过。 - Joe
2工作于22.04 - Ahmed ElMetwally
1这是一个很实用的解决方案,因为它不需要任何外壳重启,所以可以在脚本中间使用并且能够正常工作。是的,就像其他懒惰选项一样,它提供了root访问权限,但在你已经使用root的情况下,它比无根docker的设置和维护要简单得多。 - Ajax

创建了docker组,并使用以下命令将我的用户添加到其中:
sudo groupadd docker
sudo usermod -aG docker $USER

...我仍然需要为/var/run/docker.sock套接字和/var/run/docker目录设置适当的权限,以使其正常工作:
sudo chown root:docker /var/run/docker.sock
sudo chown -R root:docker /var/run/docker

退出并重新登录(使用该用户),然后您就能够在不使用sudo的情况下运行docker命令:
docker run hello-world

顺便说一句:这个问题已经在Ubuntu 21.10中修复了,只有低于这个版本的Ubuntu才需要进行此操作。

2我收到了chown: changing ownership of '/var/run/docker/netns/ingress_sbox': Operation not permitted的错误信息。 - Soren
@Soren 我刚刚再次尝试了一下,使用Ubuntu 20.04系统,之前提到的所有命令都可以正常工作。如果你在chown命令前加上sudo,应该不会收到任何错误信息。尝试重新启动计算机,登录root账户并运行两条chown命令(无需使用sudo)。然后退出root用户账户,登录你的普通用户账户,并尝试在不使用sudo的情况下使用docker。现在可以正常工作吗? - miu
只需添加组并将用户添加到该组,对我来说起作用了,但是在重启后。我使用的是Pop!_OS 20.04 LTS。如果有人想要尝试,请先重启一次,只有在不起作用的情况下再使用这个解决方案。 - Yaroslav Yakovlev
@Soren 这是因为你在 Docker 守护进程运行时尝试执行 chown 命令。请使用 systemctl stop docker 停止 Docker,然后按照这个解决方案的命令进行操作,最后使用 systemctl start docker 启动它。 - A.Casanova

Docker容器需要由超级用户运行。您可以将自己添加到docker组中(例如通过运行sudo usermod -aG docker $USER),但这会使得任何具有访问$USER帐户的人都可以轻松获得机器的root访问权限(例如通过在特权容器中挂载根卷)。
以更注重安全的方式运行非root用户的Docker容器的方法是使用Podman。从其网站上可以看到:

Podman是一个无守护进程的容器引擎,用于开发、管理和运行OCI容器。容器可以作为root或在无根模式下运行。简单来说:alias docker=podman

另一种选择是Singularity,这在HPC环境中更常见。

请提供关于为什么Docker容器必须以root用户身份运行的信息。 - GaTechThomas
2Docker可以在没有root权限的情况下运行。请参阅“以非root用户身份运行Docker守护进程(无根模式)”一节,网址为https://docs.docker.com/engine/security/rootless/。 - Erik Sjölund