Docker在容器未启动的情况下修改容器中的文件

docker容器在启动后进入容器中修改了部分文件,之后重启容器失败,此时有点束手无策,因为不启动容器就不能exec进入容器修改文件,但不修改正确文件又不能启动容器,陷入了死循环。好像没有办法。

但docker不会这么笨的,另外虽然docker容器没有启动,但docker整个都安装在本地磁盘上,它肯定能支持在磁盘上找到其对应位置直接修改文件。不错,docker就是可以直接在系统上修改其文件内容。虽然docker容器无法启动,但是docker inspect命令依然可以使用,我们利用这个命令找到它的一些执行信息,其中就有GraphDriver的相关信息:

1
2
3
4
5
6
7
8
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/over..."
"MergedDir": "/var/lib/docker/overlay2/df23df45.../merged"
"UpperDir": "/var/lib/docker/overlay2/df23df45.../diff"
"WorkDir": "/var/lib/docker/overlay2/df23df45.../work"
},
"Name": "overlay2"

Docker的graph driver主要用于管理和维护镜像,包括把镜像从仓库下载下来,到运行时把镜像挂载起来可以被容器访问等,都是graph driver做的。涉及的docker命令有Docker pull/push/export/import/load/save/build。graph driver的功能基本上是对docker的image定义的实现,而OCI的image-spec是基于docker的image spec的,所以理论dockergraph driver做的事情,都应该被image-spec的实现所覆盖。目前docker支持的graph driver有:Overlay/Aufs/Devicemapper/Btrfs/Zfs/Vfs,这些driver各有优劣。从上面的GraphDriver信息中可以看到当前的docker是用Overlay2作为graph driver的。

对于Overlay driver,其它的这里就不多涉及了,可以了解一下它的关键目录:/var/lib/docker/overlay,即上面的GraphDriver信息中的MergedDir、UpperDir、WorkDir。这个目录中存放的是镜像的每一层layer解压后的结果,以及基于每一个镜像生成容器后,对镜像合并挂载后的目录和对应的init目录。这里的id就是cache-id和mount-id。我们启动镜像时挂载的目录以及镜像中的文件都可以在这里找到。里面又分几个子目录,正是和GraphDriver信息中的MergedDir、UpperDir、WorkDir一一对应。

/var/lib/docker/overlay/<id>/merged:这是所有镜像层合并后的结果,就是容器中进程看到的结果

/var/lib/docker/overlay/<id>/upper:这是上面的只读层,用户挂载的upper层目录

/var/lib/docker/overlay/<id>/work:文件系统的工作基础目录。

对于overlay2,其UpperDir就是我们挂载的程序目录所在的位置,因此容器挂了无法启动,此时我们可以进入inspect命令结果中的UpperDir目录 :/var/lib/docker/overlay2/df23df45.../diff 里找到程序进行修改。