Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在服务器 build docker image 时服务器会卡死的问题分析及解决方案 #109

Open
lmk123 opened this issue Mar 16, 2022 · 0 comments
Labels

Comments

@lmk123
Copy link
Owner

lmk123 commented Mar 16, 2022

在分析问题之前,先说说我是怎么在服务器上更新我的后端应用的。

我在服务器上安装了 docker,当我在本地修改了代码之后,我会将代码传送到服务器里,然后在服务器里用代码 build 出 docker image 并重新生成 container。

起初,这种方式运行的很好,但随着我 build 的次数越来越多,我能明显感觉到每次 build image 的时间变得越来越久,从一开始的 20 秒,到后来的 10 分钟,而到上一次的时候,过了半小时都没有 build 成功。

镜像 build 的过程其实就只是用 yarn install 安装了项目依赖,而且也确认不是网络原因,因为从 yarn install 的日志来看,模块很快就下载好了,但卡在了 Building fresh moudes [4/4] 这一步。

而且,build 过程中还出现了 ssh 无法连接的情况,最终只能重启服务器,但这个问题也导致我无法再发布新的代码了。

从云服务器后台可以看到,在 build 过程中,除了硬盘读IOPS硬盘IO繁忙比率,其它指标都是正常的。这俩指标的曲线都到顶了,其中硬盘IO繁忙比率直接冲到了 100%。

总结一下此问题的特点:

  • 这个问题一开始是没有的,而是随着 build 的次数变多,build 的时间也变得越来越长,直到最近一次直接在 build 过程中让服务器卡死了。
  • 从指标来看,卡死的原因是硬盘IO繁忙比率冲到了 100%,但是不知道为什么在 yarn install 的 Building fresh moudes [4/4] 这一步会导致这个问题。

解决这个问题的办法有两种:

  • 找到问题的原因所在并修复
  • 既然 build 过程会导致此问题,那么只要不在服务器 build 镜像就好了

由于不知道出现问题的原因,所以目前来看最好的办法就是在本地 build 镜像,然后上传到服务器并导入。

这个过程还是蛮简单的,只涉及到三条命令:

  • docker image build: 在本地 build 镜像,并指定 -o 参数,将镜像作为 .tar 文件导出
  • scp: 将 .tar 上传到服务器
  • docmer image load: 在服务器上导入 .tar 镜像

但是,这一过程却出现了问题。

第一次尝试时,上面三条命令一切正常,但是当我用导入的镜像生成 container 运行的时候报错了:exec user process caused: exec format error。谷歌了一下找到了原因:我的开发机是 Macbook Air M1,CPU 是 arm,但服务器是 x86-64 的。

所以,普通的 docker image build 是不行了,得用 docker buildx build 来打包支持多架构的镜像。https://docs.docker.com/desktop/multi-arch/

导出我用的是 docker buildx build -o type=tar,dest=out.tar --platform=linux/amd64 .,但导入的时候用 docker image load 会报错:open /var/lib/docker/tmp/docker-import-837327978/bin/json: no such file or directory

简单 google 了下之后,改为用 docker image import 导入了 tar,但是作为 container 跑起来之后又报错了:No command specified——然而我的 Dockerfile 里明明写了 CMD 的 😂

到这里我觉得这问题一时半会儿是解决不了了,就决定找个其它时间再尝试。

此问题已解决,见 https://github.com/lmk123/docker-buildx-test

由于尝试过程中产生了很多没有用的 image,我决定清理一下,正好以前 build 过的代码镜像也一直没清理过,占用了很多硬盘空间,于是我运行了 docker image prune,然而这个命令运行了 3 分钟了没有任何反应,像极了 build image 时的表现,于是我赶紧上云服务器后台确认了一下指标,发现硬盘IO繁忙比率冲到了 82%,但是没到 100%,而且 ssh 也能正常连上去。大概 5 分钟后,命令运行完成了。

我突然想到,会不会是因为一直没清理 image 导致的这个问题?于是我又重新尝试了在服务器里 build image,结果居然 20 秒就好了,就像我第一次 build 时那样快 😂

到这里问题可以说圆满解决了,但是我仍然不明白为什么没有清理的 image 会导致这个问题 😂

@lmk123 lmk123 added the Docker label May 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant