构建 Docer 镜像失败

背景

有同事反馈发版平台线上推送失败,发版平台的推送包含3个步骤:

  1. 把包传给 deploy-dispatcher
  2. 构建 Docker 镜像
  3. 把镜像上传到 Harbor(Docker镜像仓库)

问题

问题出在第二步构建 Docker镜像,访问 Docker Daemon 报了个 could not find writer for content-type application/tar。

排查

  1. 这个异常来自 resteasy 的 httpClient。resteasy 是 jaxrs 其中一个实现,另一个常用的实现是 jersey。之前一直用的 jersey 没有报过这个异常,实现突然变成了 resteasy,判断中间一定发了版。

  2. 把代码拉下来看了依赖,有一个名为 creep 的日志组件依赖了 resteasy,所以 classpath 中有一个 resteasy-client,导致 SPI 选择了 resteasy 实现。

  3. 排除了 resteasy-client 依赖,发了个版上去观察,遇到新的异常:Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response。

  4. 看表面是 docker daemon 没有返回 符合 http 协议的报文,于是登陆 springboot-admin 打开了 org.apache.http.wire 的 DEBUG 日志级别,观测到 client 发出了完整的 http请求,收到了乱码的返回报文。

  5. 截图反馈给运维,运维查看了 docker daemon 的日志,显示 TLS 握手异常。于是让运维抓一个包 prod.cap,咋一看没发现问题:
    异常访问

  6. 由于开发环境可以正常构建镜像,于是让运维在开发环境抓一个包 dev.cap,比对一看,明显发现线上的 docker client 没有做 TLS握手
    正常访问

  7. 经过排查,是有同事在升级的过程中把 docker client 的密钥归档到另外一个目录,这边 docker client 没有检测到密钥也不报错,直接用 HTTP 访问,服务端 docker daemon 拒绝访问。

总结

官方的 Docker client 终究是个黑盒,出了问题也不要慌,大多数开源的工具都会好好打日志,根据异常栈,一个个打开 DEBUG 级别日志看,总能找到线索。
不得不说 resteasy 健壮性实属一般,虽然是 jboss出品,但依赖一上来就好几个冲突,于是当初文件网关选型的时候选了 jersey。
山穷水尽的时候再抓包吧,但不是每个运维都会这般配合就是了。

posted @ 2020-04-01 14:41  Casaa  阅读(189)  评论(0编辑  收藏  举报