一个计算机技术爱好者与学习者

0%

好好学Docker:Docker问题记录

1. 前言

本文记录使用Docker过程中遇到的问题和解决办法。

2. docker启动失败

2.1. 问题描述

docker启动卡住,查看日志

1
2
systemctl status docker -l
journalctl -ru docker

报错:

1
Error (Unable to complete atomic operation, key modified) deleting object [endpoint 622bf1a499580702606742e5f5554ac99e7c0d61abcd5d9063881fc2da33d16f afdce62ce70de2cbe5a971b05521280940947e4968c163e48c3e5252919a4fae], retrying....

2.2. 解决办法

1
2
3
4
ps -ef | grep docker
kill -9 xxx
systemctl stop containerd
systemctl start docker

3. OCI runtime create failed

3.1. 问题描述

原本可以正常启动nvidia runtime的容器,使用相同的启动命令,突然有一天开始报错:

1
2
3
4
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: process_linux.go:545: container init caused: Running hook #1:: error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: initialization error: driver error: failed to process request: unknown.

docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: process_linux.go:545: container init caused: Running hook #1:: error running hook: exit status 1, stdout: , stderr: Auto-detected mode as 'legacy'
nvidia-container-cli: initialization error: load library failed: /usr/bin/../lib64/libm.so.6: symbol __strtof128_nan, version glibc_private not defined in file libc.so.6 with link time reference: unknown.

3.2. 解决办法

尝试了重启docker、重启主机、重装nvidia-container-tookit、重装nvidia驱动,全部无效。

最终解决办法:检查libm.so.6的软链指向,修改指向到另外的libm。

1
2
cd /usr/bin/../lib64/
ln -snf libm-2.17.so libm.so.6

4. error pulling image configuration

4.1. 问题描述

docker pull ubuntu 报错:

1
2
3
4
Using default tag: latest
latest: Pulling from library/ubuntu
6b851dcae6ca: Pulling fs layer
error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/99/99284ca6cea039c7784d1414608c6e846dd56830c2a13e1341be681c3ffcc8ac/data?verify=1687183284-D5%2FDxEvl7V%2BLtRcgWmwP0MDFiTo%3D: dial tcp 104.18.125.25:443: i/o timeout

4.2. 问题分析

production.cloudflare.docker.com 的IP是会变化的,当前的这个 104.18.121.25 刚好被墙了,无法访问。
查看是否被墙的办法:访问ITDOG,输入 production.cloudflare.docker.com 这个网址。

4.3. 解决办法一

配置使用镜像站,从镜像站拉取镜像,避开 production.cloudflare.docker.com 这个域名。

1、编辑docker配置文件

1
vim /etc/docker/daemon.json

添加 registry-mirrors 配置,配置方法参考《Docker镜像站的配置和使用》

2、重启docker

1
2
systemctl restart docker
docker info

4.4. 解决办法二

解决办法一,有时也不可行,因为有可能全国都被墙了,镜像站也无法从源站拉取我们需要的镜像。

此时只能使用终极解决办法:使用梯子。
方法一:机器上直接配置使用梯子,配置方法参考《Linux配置网络代理》
方法二:搭建一个docker本地镜像站,配置使用梯子;其他机器配置使用这个docker镜像站。配置方法参考《Docker镜像站的配置和使用》

5. failed to compute cache key

5.1. 问题描述

已知Dockerfile内容为:

1
2
3
FROM alpine:3.7.3
WORKDIR /home/work
COPY Dockerfile .

Dockerfile所在目录,执行docker build报错:

1
failed to compute cache key: failed to calculate checksum of ref moby::heujqm1lca2el12jsbquzoarg: "/Dockerfile": not found

5.2. 解决办法

检查 .dockerignore 文件,大概率是因为该文件中忽略了 Dockerfile

6. Docker打满CPU内存问题

6.1. 问题描述

系统环境:

  • 主机系统CentOS7.9,kernal 4.19.188-10.el7.ucloud.x86_64
  • K8S集群版本1.20.14,calico版本3.22.1,集群是使用sealos4.2.3安装的,详情参考《sealos入门篇》
  • Docker版本19.03.15

当一个节点上的pod数量超过一定数量,或者pod比较繁忙时,CPU和内存就会被Docker进程进行打满。

  • pod的limits都是进行过限制的,总和远小于宿主机CPU资源总量
  • 通过容器监控看,pod总的CPU资源用量远小于100%,大约只有20%到30%
  • 通过主机监控看,busy system(cpu处于核心态的占比)约90%,busy user(cpu处理用户态的占比)约6%
  • 通过主机监控看,从busy system占比90%开始,内存使用率逐步增加,经过一个小时左右内存使用率增长到100%

此时查看docker日志,发现大量报错:

1
Handler for GET /v1.40/containers/xxx/json returned error: write unix /var/run/docker.sock->@: write: broken pipe

6.2. 解决办法

没有检索到解决办法。
尝试升级Docker版本到 24.0.6 ,无效。

经过和正常集群的对比,发现有问题主机的内核版本为 4.19.188-10.el7.ucloud.x86_64 ,没问题主机的内核版本为 5.4.148-1.el7.elrepo.x86_64 。
中间差了一个大版本,而且有问题主机的内核版本还是ucloud定制版。
因此,尝试升级内核,升级方法参考《CentOS7内核升级》
升级后,问题消失了。。。

7. Docker启动容器很慢问题

7.1. 问题描述

1
docker run --name test -d busybox tail -f /dev/null

Docker启动任何容器都很慢,需要十几秒甚至几分钟才能启动成功。

7.2. 解决办法

查看一下主机磁盘使用情况,可能是IO使用率高。
找到占用大量IO的进程,判断是否是正常占用,非正常占用的话就干掉它。

8. docker run的内容重定向到文件

8.1. 问题描述

使用docker批量运行一些任务时,需要多个容器同时运行,同时容器跑完即删,例如:

1
2
3
4
5
6
7
for i in `seq 0 3`;do
screen -dmS part${i} docker run --rm \
-e PART=${i} \
-v /data/test:/data/test \
test-image-name:latest \
/bin/bash -c "xxx"
done

想要查看某个容器的输出时,使用命令 screen -ls + screen -r yyy.partN 实现。
但是,这样并不方便查看输出,出错时容器直接就没了,不方便追查问题。
因此,我们需要把docker run的内容重定向到文件中,该怎样修改命令?

8.2. 解决办法

单独执行 docker run --rm 时,怎样重定向内容到文件?
答:重定向标准输出和错误输出到文件即可。
方法一:直接重定向,这种方法拿到的数据的最全的。

1
docker run --rm nginx > output.log 2>&1

方法二:使用tee重定向,但是拿到的是缺失的数据,这是因为管道符只能重定向标准输出。

1
2
docker run --rm nginx | tee output.log # 缺失nginx日志输出
docker run --rm nginx 2>&1 | tee output.log # 缺失ctrl+c后的数据

screen -dm + docker run --rm 时,怎样重定向内容到文件?
答:首先,上面的两种办法,经测试都是不可行的,需要考虑screen的输出机制。
执行 screen -dm 时,screen创建一个新会话并立即后台运行(Detached)。当screen后台运行时,它关闭了标准输入、输出和错误流。

方法一:打开screen的标准输出,输出文件名不可控,默认为 screenlog.0

1
screen -L -dmS nginx docker run --rm nginx

方法二:在screen session中使用tee

1
screen -dm bash -c "docker run --rm nginx 2>&1 | tee output.log"

方法三:改用nohup(推荐)

1
nohup docker run --rm nginx > output.log 2>&1 &

综上,脚本修改为:

1
2
3
4
5
6
7
for i in `seq 0 3`;do
nohup docker run --rm --name part${i} \
-e PART=${i} \
-v /data/test:/data/test \
test-image-name:latest \
/bin/bash -c "xxx" > part${i}.log 2>&1 &
done

9. /run 目录下没有空间

9.1. 问题描述

docker run启动一个容器时,报错:

1
docker: Error response from daemon: failed to create task for container: failed to start shim: write /run/containerd/io.containerd.runtime.v2.task/moby/781958621c259371c2fec92ea1ab86f0937fa480bcf4aefc15d30ce3c5da90eb/config.json: no space left on device: unknown.

9.2. 问题排查解决

1、查看磁盘使用情况

1
df -h

发现 /run 目录已经打满

1
2
3
4
5
6
Filesystem      Size  Used Avail Use% Mounted on
/dev/root 29G 16G 14G 53% /
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 794M 794M 0 100% /run
...

2、查看 /run 目录下是哪些文件占用了磁盘

1
du -h --max-depth=1 /run

3、找到占用磁盘空间的文件,并清理

  • 本文作者: 好好学习的郝
  • 原文链接: https://www.voidking.com/dev-docker-problem/
  • 版权声明: 本文采用 BY-NC-SA 许可协议,转载请注明出处!源站会即时更新知识点并修正错误,欢迎访问~
  • 微信公众号同步更新,欢迎关注~