你在一台刚装好、或者从别人手里接过来的 Linux 机器上敲下 docker ps,想看看有哪些容器在跑。命令敲下去,等来的不是列表,而是一句让你怀疑人生的报错——你明明记得这个软件装过了。
现象
报错长这样:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
有时还会顺带一句 permission denied while trying to connect to the Docker daemon socket。你 which docker,能查到二进制;docker --version 也正常打印版本号。可就是连不上。
根因
这里的关键,是要意识到 Docker 不是一个程序,而是两个。
- 一个是
docker这个命令行工具,它只是一个客户端,负责把你的命令转成请求发出去; - 另一个是
dockerd这个守护进程(daemon),它才是真正干活、管理镜像和容器的那一方。
两者之间通过一个 Unix domain socket 通信,默认路径就是 /var/run/docker.sock。客户端把请求写进这个 socket,守护进程从另一头读走。
问题就出在这:安装 Docker 时,未必会把守护进程设为开机自启并立即启动。很多发行版、很多"自带 Docker"的镜像或模板,只把二进制包放了进去,服务单元存在但没有 enable,也没有 start。于是:
docker二进制在 →--version正常;dockerd没跑 →/var/run/docker.sock这个文件根本不存在;- 客户端找不到 socket,只能报"守护进程没在跑"。
所以那句 "Is the docker daemon running?" 不是修辞,是字面意思——它真的没在跑。
解决
先确认状态,再启动:
# 看服务当前状态:是 inactive (dead) 还是 failed
systemctl status docker
# 启动,并设为开机自启(enable + start 合并在一条里)
systemctl enable --now docker
# 验证守护进程真的活了
docker info
docker ps
enable --now 是两件事的合并写法:enable 把服务登记进开机自启,now 表示"顺手现在也启动它"。只 start 不 enable,重启后又没了;只 enable 不 start,当前这次会话还是连不上。
如果 systemctl status docker 显示的是 failed 而不是 inactive,那说明它尝试启动过但失败了,这时要往后翻几行看 journalctl -u docker 的报错——常见的有配置文件语法错、数据目录权限不对、和别的服务抢同一个 socket。这类才是真正需要修的。
另外,如果报的是 permission denied 而不是"连不上",那服务是活的,问题在权限:当前用户不在 docker 组里。可以:
# 把当前用户加进 docker 组(重新登录后生效)
sudo usermod -aG docker $USER
注意,加入 docker 组等价于给了这台机器上的 root 权限(组内成员可以挂载宿主机任意目录进容器),这是安全上要认真对待的一件事,不要随手给不可信的用户加。
延伸与预防
这条坑的通用价值,是那套排查顺序:服务在不在 → 进程活没活 → 连得上连不上 → 权限够不够。
很多人遇到"命令报错",第一反应是重装软件、怀疑版本、去搜"docker 命令报错怎么办"。可这里命令、版本、安装都是好的,缺的只是"服务没被拉起来"这一环。把"客户端与服务端分离"这件事记在心里,以后遇到数据库(psql 连不上 postgresql 服务)、消息队列、缓存这些同样"客户端/服务端分离"的软件,都能少走弯路。
至于预防:接手一台新机器、或写安装脚本时,装完就把 systemctl enable --now <服务> 写进去,别假设"装好了就等于跑起来了"。