← 中文资源

简体中文版本

Docker 权限拒绝 — 无法连接守护进程 socket

从用户组、socket 权限、Docker context 与 rootless 路径排查 docker.sock 的 permission denied,避免用 777 降低安全性。

阅读英文原文

现象

执行 docker 命令报 permission denied while trying to connect to the Docker daemon socket;sudo docker ps 正常而普通用户失败;重新登录后仍失败;容器内挂载 docker.sock 时同样报错。

诊断

确认用户组、socket 权限和实际连接端点:

id
getent group docker
ls -l /var/run/docker.sock
docker context ls
echo "DOCKER_HOST=$DOCKER_HOST"

getent 里有用户但 id 里没有 docker,说明当前会话还是旧的组信息,需要重新登录;newgrp docker 只对当前 shell 生效。socket 为 660 root:docker 时只有 root 和 docker 组成员可写;socket 不存在则说明守护进程或 socket 单元没起来。若 context 指向 rootless 或远程端点,默认 socket 的权限就无关了。

根因

Docker CLI 通过 Unix socket 调用守护进程,访问权限由文件权限决定。调用进程缺少写权限,或者连接的根本不是刚检查过的那个 socket,于是被拒绝。

修复

把用户加入 docker 组并开启新会话:

sudo usermod -aG docker "$USER"
newgrp docker
docker context use default
# rootless 环境:
# docker context use rootless

rootless Docker 使用 $XDG_RUNTIME_DIR/docker.sock,可完全绕开该组。不要 chmod 777 socket:docker 组等价于 root 权限,不可信用户应使用 rootless 模式。

验证

在新登录 shell 中确认 id 含 docker,直接运行 docker info 与 docker run --rm hello-world 成功;context 端点与守护进程 socket 路径一致;journalctl -u docker 中没有新的 AppArmor 或 SELinux 拒绝记录。