文章目录

  • (1)前言
  • (2)容器的存储原理
  • 原理
  • 实验
  • (3)docker inspect方式处理
  • (4)docker cp方式处理


(1)前言

最近一次开发工作中在处理一个ElasticSearch容器的时候误操作修改了其中一个初始内存的大小,导致一直启动失败,但是对应的配置并没有挂载到本地,而现在我又无法通过docker exec -it 进入到容器内修改,最终在多次处理之后通过docker inspect的方式获取到容器的映射到宿主机的实际存储位置,通过在宿主机内定位到容器的实际存储位置后,修正错误配置并重启成功。在处理容器的时候很可能遇到类似的问题,对于一些无状态的容器可以直接拉取创建,但是对于一些有状态的容器不敢随意的删除重新创建,所以需要一些合理的方式去处理类似的问题,通过了解主要俩种方式
【1】通过docker inspect的方式定位物理存储位置,并修正
【2】通过docker cp的方式进行覆盖处理,完成问题修复

(2)容器的存储原理

原理

Docker 其中一种常用的联合文件系统解决方案是OverlayFS ,了解了这个就会知道Docker存储的一些原理。

在 Docker 中 OverlayFS 文件驱动被分为了两种,一种是早期的overlay,不推荐在生产环境中使用,另一种是更新和更稳定的overlay2,推荐在生产环境中使用。

我们可以通过docker info命令查看当前docker使用的存储机制,下图可以看到可以看到 Storage Driver 为 overlay2

容器 不定期会出现 device are busy 容器异常情况处理操作_重启


overlay2 和 AUFS 类似,它将所有目录称之为层(layer),overlay2 的目录是镜像和容器分层的基础,而把这些层统一展现到同一的目录下的过程称为联合挂载(union mount)。overlay2 把目录的下一层叫作lowerdir,上一层叫作upperdir,联合挂载后的结果叫作merged。

overlay2 文件系统最多支持 128 个层数叠加,也就是说你的 Dockerfile 最多只能写 128 行,不过这在日常使用中足够了。

OverlayFS 将镜像层(只读)称为 lowerdir,将容器层(读写)称为 upperdir,最后联合挂载呈现出来的为 mergedir。文件层次结构可以用下图表示。 从图中我们也可以看出相比 AUFS,文件层更少,这也是 OverlayFS 相比 AUFS 性能更好的一个原因。

容器 不定期会出现 device are busy 容器异常情况处理操作_docker_02


overlay2 是这样储存文件的:overlay2将镜像层和容器层都放在单独的目录,并且有唯一 ID,每一层仅存储发生变化的文件,最终使用联合挂载技术将容器层和镜像层的所有文件统一挂载到容器中,使得容器中看到完整的系统文件。

实验

当前使用的容器是MySQL,容器ID是5bbbd8b87f78

容器 不定期会出现 device are busy 容器异常情况处理操作_docker_03


通过docker inspect查看容器的详细信息,定位到GraphDriver位置。

容器 不定期会出现 device are busy 容器异常情况处理操作_java_04


【1】在宿主机内对应的UpperDir目录下创建一个测试文件,然后检查容器内是否能够找到,同时也查看下MergedDir合并后的结果

进入到上图所示的UpperDir目录下,并创建一个test.txt文件,添加内容anhui hefei

容器 不定期会出现 device are busy 容器异常情况处理操作_docker_05


然后进入到容器内,如下图所示可以看到已经映射到容器内部了,其实这里展示的就是刚才的文件位置

容器 不定期会出现 device are busy 容器异常情况处理操作_docker_06


然后退出容器,在查看MergedDir目录下的文件信息

容器 不定期会出现 device are busy 容器异常情况处理操作_Docker_07


可以看到在MergedDir有测试文件,正如上面原理说的MergedDir目录是镜像文件和容器读写文件的合并文件【2】在容器内修改一个文件,然后到宿主机到UpperDir目录和MergedDir检查

继续进入到容器,新增一个测试文件b.txt,可以看到在容器内创建或者修改的文件是会显示在UpperDir目录下的,同理也会在MergedDir目录下展示

容器 不定期会出现 device are busy 容器异常情况处理操作_重启_08

(3)docker inspect方式处理

在经过上面的简单原理分析之后,那么我们就能知道如何通过docker inspect (containername)
的方式去处理一个无法启动或者处于停止状态的容器了
【1】通过docker inspect (containername)定位到容器的宿主机UpperDir位置
【2】根据具体的问题修复问题,此时相当于就是进入了容器修改
【3】重启容器即可

(4)docker cp方式处理

除了上面的解决方式外,还可以通过一个小技巧解决,那就是容器和宿主机的文件复制方式,通过将容器内错误的配置文件复制到宿主机,然后再宿主机内修改,修复完成之后在复制覆盖回去,然后重启容器,这个方式也可以解决

$ docker cp CONTAINER:FILEPATH LOCALFILEPATH
 $ vi LOCALFILEPATH
 $ docker cp LOCALFILEPATH CONTAINER:FILEPATH