docker 版本不兼容:client 与 daemon API version 速查
更新时间:2026-10-24。FAQ 速查页,面向
docker命令敲下去、守护进程回一句「版本对不上」的同学。docker 版本不兼容的本质是客户端与守护进程各说各的 API 方言:docker CLI 与 daemon 之间走 REST API,每次握手要协商一个双方都会说的 API 版本号;客户端太新、daemon 太老(或反过来)时协商失败,命令直接夭折。病灶收敛在六根轴上:客户端新于服务端、老 daemon 配新 client、DOCKER_API_VERSION 手动钉死协商、CI 镜像里客户端版本漂移、daemon 设了最低 API 版本门槛、DOCKER_HOST 指到版本不同的远程 daemon。本篇管「协商失败」;命令能通但起容器失败的场景看 docker 权限被拒速查 与 docker 容器端口连接被拒速查。
本文要回答的问题
client is newer than server这条报错里两个版本号分别是谁的?- docker 的 API 版本协商机制是怎么工作的,什么时候会失败?
DOCKER_API_VERSION环境变量什么时候该设、设成什么?- 为什么 CI 里昨天能跑的 job 今天突然报 API version 错?
DOCKER_HOST指向远程 daemon 时为什么会突然版本不兼容?
一、报错原文与典型现象
版本不兼容的报错措辞相当标准,先对号入座(远程地址以 <服务器地址> 占位):
$ docker ps
Error response from daemon: client is newer than server
(client API version: 1.44, server API version: 1.41)# 反方向——daemon 太新、客户端太老:
$ docker version
Client: ... API version: 1.41
Server: ... API version: 1.45
$ docker compose up
Error response from daemon: client version 1.41 is too old.
Minimum supported API version is 1.44, please upgrade your client to a newer version# DOCKER_HOST 指到远程老 daemon 的场景:
$ DOCKER_HOST=tcp://<服务器地址>:2375 docker info
Error response from daemon: client is newer than server
(client API version: 1.44, server API version: 1.40)读报错抓两个数字:client API version 是你本机 CLI 会说的最新方言,server API version 是 daemon 会说的最新方言。client is newer than server = 客户端走在了 daemon 前面;client version ... is too old = 反过来,daemon 升级后把最低门槛抬高了。两者修法方向相反,别看反。
二、病因处置速查表
| 报错现象 / 场景 | 可能原因 | 快速验证 | 处置 |
|---|---|---|---|
| client is newer than server | CLI 比 daemon 新 | docker version 对照两端 | 降级 CLI 或升级 daemon,或钉 DOCKER_API_VERSION |
| client version is too old | daemon 升级后抬了最低 API 门槛 | 同上 | 升级客户端到新版 |
| 只有某台机器报错 | 该机器 CLI 装错来源/版本漂移 | docker version 与正常机对比 | 统一安装来源与版本 |
| CI 今天突然报错 | CI 镜像里 docker CLI 自动升级 | 比对前后 job 的 CLI 版本 | 钉死 CI 镜像 tag 与 CLI 版本 |
| 设了 DOCKER_API_VERSION 后报别的错 | 钉的版本低于功能所需 | 去掉变量复测 | 钉到 daemon 支持的版本,别钉太老 |
| DOCKER_HOST 远程报错 | 远程 daemon 版本老 | 本地直连远程对比 version | 升级远程 daemon 或本地降 CLI |
| 第三方工具报错(非 CLI) | SDK 写死高 API 版本 | 看工具配置的 api version | 工具侧降版本或开自动协商 |
| 升级 daemon 后老脚本挂 | 老脚本依赖被移除的旧 API | 逐条复跑脚本 | 迁移脚本到新 API/CLI 语义 |
三、排查决策图
下面这张图是标准排查路线,颜色按角色区分:红是报错入口与命中的根因,蓝是排查动作,绿是通过分支,橙是修复动作,紫是防复发沉淀。
读这张图抓住主线:docker version 一条命令同时给出两端版本,这是定位的起点;方向看错(client newer 与 too old 是反的)是最常见误操作。第二步查环境变量——DOCKER_API_VERSION 与 DOCKER_HOST 这两个隐形开关经常才是真正的肇事者。
四、逐条排查展开
先跑 docker version 拿两端数字。 它同时输出 Client 段与 Server 段的 API version——注意这条命令本身在协商失败时也可能只能输出 Client 段,Server 段报错,这个「只能看到一半」的现象本身就是证据。
docker version
# Client 段看 API version,Server 段看 Server API version 与最低支持版本协商机制与降级开关 DOCKER_API_VERSION。 正常情况下 CLI 会自动降级到 daemon 支持的版本(这叫版本协商),所以「CLI 略新」通常不报错。报 client is newer than server 的场景往往是协商没发生——比如老版本 CLI 不带协商逻辑、或中间走了某些 SDK。这时显式钉一个 daemon 支持的版本即可绕过:
DOCKER_API_VERSION=1.41 docker ps # 钉到 server 支持的版本
# 要长期生效就写进 shell profile 或 CI 环境变量注意别钉得太老:API 太低的会话里新功能(buildx 的某些能力、新 compose 语义)用不了,会引出第二类莫名其妙的报错。钉的值以 docker version Server 段显示的版本为准。
反方向:daemon 抬了最低门槛。 新版 daemon 会声明最低支持的 API 版本,老客户端低于门槛直接拒——client version ... is too old 就是这条。这种情况没有降级开关可救,正路是升级客户端。服务器升级 docker 前,把连它的所有客户端(含 CI、脚本机、同事笔记本)的版本列一遍,是避免「升完 daemon 全员挂」的关键动作。
CI 客户端漂移是「昨天好的今天挂」的头号来源。 CI 镜像如果写的是 docker:latest 或包管理器 apt install docker-cli 不钉版本,上游一发新版,你的 CLI 就悄悄超前于 CI 所连的 daemon。处置:CI 镜像钉具体 tag(如 docker:27-cli 这类明确版本),升级走变更评审而不是被动跟随。同理,compose 插件版本也随 CLI 镜像走,要一起钉。
DOCKER_HOST 指向远程时的双端错位。 DOCKER_HOST=tcp://<服务器地址>:2375 把你本机 CLI 接到了远程 daemon 上——两端版本从此脱钩:本机 CLI 跟着你本机升级,远程 daemon 跟着服务器运维节奏走。某天本机升了 CLI,远程没动,就撞协商失败。排这类错先问一句「我连的是哪台 daemon」:docker context ls 与 echo $DOCKER_HOST 看清楚再查版本。处置方向与本地一致:钉 DOCKER_API_VERSION、降本机 CLI、或升远程 daemon。
第三方 SDK 与工具的写死版本。 Portainer、各类语言的 docker SDK、老脚本里 curl --unix-socket ... /v1.24/... 这种把 API 版本写进 URL 的写法,都不会自动协商。daemon 升级后这些调用可能撞「too old」或语义变更。处置:SDK 优先用其「自动协商」选项;裸 curl 调用把 URL 里的版本号抽成配置项,跟随 docker version 输出。
升级 daemon 的兼容性检查清单。 升之前:列出全部客户端来源(本机 CLI、CI、远程 DOCKER_HOST 用户、SDK 工具)及其 API 版本;查新 daemon 的最低支持 API 版本;预留回退包。升之后用 docker version 与一条真实业务命令(比如 docker compose ps)双重复验,别只看 daemon 进程活着。
docker context 是多头 daemon 时代的显性开关。 一台开发机同时连本机 daemon、测试机、远程构建器时,docker context use 比反复改 DOCKER_HOST 更可控——每个 context 记下目标地址,切换时一目了然。排版本错时先 docker context ls 与 docker context inspect 看当前指向哪端,很多「莫名其妙的版本错」其实是切错了 context、连到了一台老 daemon 上。把这个确认动作写进排错手册第一步,能省一半无用功。
五、规范做法与预防
- 安装来源统一:团队约定 docker CLI/daemon 只从官方仓库装,版本写进装机脚本,杜绝「某台机器版本漂移」。
- CI 镜像钉 tag:禁止
docker:latest进流水线,CLI 与 compose 插件版本随镜像 tag 一起钉。 - 升级 daemon 先普查客户端:升级公告里附客户端最低版本要求,提前通知 DOCKER_HOST 用户。
- SDK 用自动协商:封装内部工具时把 API 版本留成配置,默认走协商不写死。
- DOCKER_API_VERSION 只当创可贴:应急降级可用,长期方案仍是对齐两端版本。
- 复验双段闭环:修完
docker version两端都出数 + 一条真实命令跑通,才算闭环。
这一篇在知识体系里的位置
本篇是 docker 排错速查簇的版本篇,定位「客户端与 daemon 协商失败」:协商通过之后,拉镜像阶段的报错看 docker 镜像找不到速查 与 docker 拉取限流速查;命令期权限问题看 docker 权限被拒速查;容器运行期的缺库与端口问题看 docker 容器缺动态库速查 与 docker 容器端口连接被拒速查。docker version 双段对照、DOCKER_API_VERSION 应急降级、CI 钉版本三件套,是一切版本类排错的通用底盘。
一句话总结
docker 版本不兼容先 docker version 拿客户端与 daemon 两端 API version,按报错措辞定方向:client is newer than server 是 CLI 超前——应急用 DOCKER_API_VERSION=<server 版本> 钉住协商、根治靠对齐两端版本;client version is too old 是 daemon 抬了最低门槛——只能升级客户端。CI 报错的头号来源是镜像没钉 tag 导致 CLI 悄悄升级,DOCKER_HOST 远程场景先确认连的是哪台 daemon 再查版本。安装来源统一、CI 钉死镜像 tag、升级 daemon 前普查全部客户端,这类报错即可基本绝迹。