在 VPS 上运行 docker ps、docker compose up 或部署脚本时,出现 Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?,先不要重装 Docker。这条错误只说明 Docker 客户端没有成功连接到它选择的 daemon,原因可能是服务没启动、连接地址错了、Rootless 与系统级 Docker 混用,也可能是修改配置后 daemon 启动失败。
本文以使用 systemd 的 Linux VPS 为主,按“确认连接目标 → 检查服务状态 → 读取失败日志 → 修复对应原因 → 验证业务”的顺序排查。Docker Desktop、Kubernetes 的容器运行时和托管面板自带的独立运行时,应先按各自的管理方式确认服务位置。
| 看到的错误或状态 | 优先排查 |
|---|---|
Cannot connect ... unix:///var/run/docker.sock | 本机系统级 daemon 是否运行、客户端是否选对 socket |
地址是 /run/user/1000/docker.sock 一类路径 | 对应用户的 Rootless Docker 服务与登录会话 |
地址是 tcp://... 或 ssh://... | context、环境变量和远端连接;本机重启 Docker 可能无效 |
permission denied while trying to connect | socket 权限、用户身份;不要先判定 daemon 已停止 |
docker.service: Failed 或 Start request repeated too quickly | journal 中最早的实际失败原因 |
Unit docker.service could not be found | 是否只装了 CLI,或实际采用 Rootless、其他安装方式 |
docker --version 只证明客户端命令存在,不能证明 daemon 正常。更有用的是 docker version:如果只有 Client 信息、Server 部分报错,就继续下面的连接排查。Docker 对这类错误的定义见官方 daemon 排障文档。
在发生报错的同一个用户、同一个终端环境运行:
docker version
docker context show
docker context ls
docker context inspect
env | grep -E '^DOCKER_(HOST|CONTEXT|TLS_VERIFY|CERT_PATH)='
环境变量命令没有输出通常只是这些变量未设置。重点看 context 的 Docker endpoint 和报错里的地址。DOCKER_HOST、DOCKER_CONTEXT 与命令中的 --host、--context 会影响连接目标;不能只看 docker context ls 的星号就认定所有命令都在访问它。具体行为见 Docker contexts 文档。
如果你本来就要连接远端 daemon,先检查远端主机、SSH 登录或 TLS 配置,不要把 context 改回本地来掩盖故障。如果你确认这台 VPS 应使用普通的本地系统级 Docker,可以做一次不修改配置的对照测试:
env -u DOCKER_HOST -u DOCKER_CONTEXT -u DOCKER_TLS_VERIFY -u DOCKER_CERT_PATH docker --context default info
这只为当前命令排除相关连接环境变量,并明确使用 default context。若它成功而原命令失败,优先修正部署脚本、Shell 启动文件或 CI 环境里的连接设置。不要全局清空所有 Docker 配置,也不要删除还在使用的远端 context。
特别留意 sudo docker ... 与普通用户的差异:它们可能读取不同账号的客户端配置,看到不同的 context。sudo 下能列出容器,并不自动说明普通用户连接的是同一个 daemon。
以下命令针对系统级 Docker Engine:
sudo systemctl status docker.service docker.socket --no-pager -l
sudo systemctl is-active docker.service
sudo journalctl -u docker.service -b --no-pager -n 100
sudo ls -l /var/run/docker.sock
socket 文件存在不代表 daemon 已经能正常响应;反过来,某些安装方式也不使用默认 socket。确认本机确实应该使用 /var/run/docker.sock 后,可以用显式地址检查,减少 context 与用户配置的干扰:
sudo env -u DOCKER_HOST -u DOCKER_CONTEXT -u DOCKER_TLS_VERIFY -u DOCKER_CERT_PATH docker --host unix:///var/run/docker.sock info
如果这条命令成功,而普通用户访问同一 socket 报 permission denied,服务本身已经可达,下一步应处理用户权限。具体见 Docker socket 与用户组权限排查。不要使用 chmod 666 /var/run/docker.sock 作为修复;拥有 Docker socket 访问权通常意味着能够控制宿主机上的高权限操作。
确认使用的是系统级 Engine、日志没有配置或数据错误后,启动服务:
sudo systemctl start docker.service
sudo systemctl is-active docker.service
启动方式与系统有关,见 Docker daemon 启动文档。如果命令失败,不要连续反复执行,直接进入日志排查。
先区分 CLI 和 daemon 是否都存在:
command -v docker
command -v dockerd
systemctl list-unit-files 'docker*' 'containerd*'
只安装 docker 客户端并不会提供本机 Engine。也可能使用了 Rootless、Snap、手动二进制或面板管理的服务。按实际安装来源补齐或管理对应组件,不要直接把另一个安装渠道的包叠加上去。普通系统级 docker.service 不存在时,创建一个随意拼出的 unit 文件通常会让 socket、containerd 和启动参数更难排查。
查看较完整的日志和生效的服务配置:
sudo journalctl -u docker.service -b --no-pager -n 200
sudo systemctl cat docker.service
sudo systemctl show docker.service -p ExecStart -p FragmentPath -p DropInPaths
日志末尾的 Failed to start Docker、exit-code 或 Start request repeated too quickly 是结果。往前找 dockerd 首次退出附近的具体内容,例如配置解析失败、参数重复、磁盘写入失败或网络控制器初始化错误。Docker 在 Linux 上的日志读取方式见官方 daemon 日志文档。
不要为了看到更多输出,在 systemd 服务尚未停止时再手动启动第二个 dockerd。两个进程争用 socket、PID 或数据目录会增加新的错误。
普通 Linux Engine 默认配置文件是 /etc/docker/daemon.json;若 ExecStart 指定了 --config-file,以实际路径为准。只有文件存在时才检查它:
sudo python3 -m json.tool /etc/docker/daemon.json
sudo dockerd --validate --config-file=/etc/docker/daemon.json
第一条只检查 JSON 语法;第二条让 dockerd 验证配置并退出,不启动服务。configuration OK 表示这份配置通过校验,仍不能证明磁盘、网络与实际 systemd 启动参数都正常。--validate 的定义见 dockerd CLI 参考。
如果文件路径不存在,不要为了运行检查就新建空配置。若需要修改现有文件,先保存备份,再只修正有问题的字段:
sudo cp -a /etc/docker/daemon.json /etc/docker/daemon.json.backup.$(date +%Y%m%d%H%M%S)
sudo nano /etc/docker/daemon.json
sudo dockerd --validate --config-file=/etc/docker/daemon.json
常见问题包括尾部逗号、JSON 中加入注释、选项名称拼错,以及把其他 Docker 版本的完整配置模板照搬过来。保留原有 data-root、存储和网络设置;用一份空模板覆盖配置可能让 daemon 连接到另一套数据目录,表现成“容器全部不见了”。
若日志明确出现 directives are specified both as a flag and in the configuration file: hosts,检查 systemctl cat docker.service 是否有 -H fd://、-H unix://... 等参数,同时检查 JSON 中的 hosts。
同一选项在命令行与 JSON 中重复设置,哪怕值相同,也可能阻止 daemon 启动。对只需要本地 socket 的常规 VPS,通常可以撤销自己新增的 hosts 配置,让软件包的服务配置继续负责监听;但如果这台机器确实需要自定义 endpoint,就应按实际 unit 和官方远程访问配置统一管理。
不要复制一条精简的 ExecStart=/usr/bin/dockerd 覆盖所有原始参数。它可能丢失 containerd 地址、socket activation 或发行版所需设置。单独运行配置校验也未必能发现与 systemd 参数的重复,最终应同时核对 JSON、unit 和启动日志。
Docker API 具有很高权限;不要为了让连接成功,就增加一个未经认证、监听公网的 2375 端口。
如果日志指向写入失败、内存不足或网络/存储初始化失败,先读取资源与内核日志:
df -h
df -i
free -h
sudo journalctl -k -b --no-pager -n 200
磁盘有 GB 空间但 inode 耗尽,仍可能无法创建文件;内核 OOM killer 也可能终止 daemon。网络或存储初始化报 operation not permitted 时,还应确认 VPS 的虚拟化环境是否允许对应内核能力。根据具体错误处理资源、内核或服务商限制,不要直接关闭防火墙、改存储驱动或重新格式化目录。
尤其不要删除 /var/lib/docker 或实际 data-root 来“恢复启动”。其中可能有镜像、容器可写层及 Volume 数据;daemon 不可用时,docker system prune 也不是通用自救方法。
如果 endpoint 是 /run/user/<UID>/docker.sock,或 docker info 曾显示 rootless,应该检查拥有这套 daemon 的用户服务,而不是只看 sudo systemctl status docker。
以该用户直接通过 SSH 登录后运行:
id -u
systemctl --user status docker.service --no-pager -l
journalctl --user -u docker.service -b --no-pager -n 100
docker context ls
确认已安装且应该运行后:
systemctl --user start docker.service
如果 rootless context 确实存在,可以明确验证它:
env -u DOCKER_HOST -u DOCKER_CONTEXT -u DOCKER_TLS_VERIFY -u DOCKER_CERT_PATH docker --context rootless info
Rootless 的默认 daemon 配置是 ~/.config/docker/daemon.json,数据目录与系统级 Engine 也不同。不要把系统级 Docker 的容器清单与 Rootless 清单混为一谈。路径和管理方式见 Rootless 使用说明。
如果 systemctl --user 报 Failed to connect to bus,先检查是否通过 sudo su 或类似方式切换了用户,导致用户登录会话未正确建立。使用该用户的正常 SSH 登录会话再检查,相关原因见 Rootless 排障文档。
需要用户服务在退出 SSH 后及开机时继续运行时,可在了解影响后启用该用户的服务与 lingering:
systemctl --user enable docker.service
sudo loginctl enable-linger "$(id -un)"
这让该用户的服务可以在未登录时运行。它不会把 Rootless 的 socket 变成 /var/run/docker.sock,客户端仍需使用正确的用户和 endpoint。
普通系统级 Engine 的配置通过检查后启动。如果修改过 unit 或 drop-in,先执行 sudo systemctl daemon-reload;只改 JSON 时不需要这一步。若服务因反复失败触发速率限制,可在原因已修复后清除失败状态,再启动:
sudo systemctl reset-failed docker.service
sudo systemctl start docker.service
sudo systemctl is-active docker.service
sudo journalctl -u docker.service -b --no-pager -n 50
如果 daemon 原本还在运行,需要应用配置而执行 restart,先安排业务窗口;默认情况下重启 daemon 可能影响运行中的容器。reset-failed 只清除失败状态,不会修好配置、资源或权限问题。
随后回到最初报错的用户和环境检查:
docker version
docker info
docker ps -a
成功标准包括:Server 信息能读取、endpoint 是你预期的 daemon、原有容器和 Volume 仍存在、关键业务能正常访问。不要只看到 active 就结束。若 daemon 已经可连接但某个容器仍反复退出,应继续查该容器日志,而不是再次重装 Engine。
- daemon 正常但普通用户被拒绝:docker.sock、用户组与挂载权限排查。
- VPS 开机后服务没有恢复:systemd 与 Docker 自启动排查。
- daemon 能连接但容器一直重启:退出码、健康检查与 OOM 排查。
- 容器尚未启动就卡在下载镜像:Docker pull 超时、429 与证书错误排查。
排查这条错误最有效的顺序是:先确认连接目标,再读 daemon 状态与失败日志,修复后验证原有业务。这样能避免把客户端配置错误、权限问题和实际 daemon 启动失败混在一起处理。
