Docker在容器未启动的情况下修改容器中的文件
docker容器在启动后进入容器中修改了部分文件,之后重启容器失败,此时有点束手无策,因为不启动容器就不能exec进入容器修改文件,但不修改正确文件又不能启动容器,陷入了死循环。好像没有办法。
另外虽然 docker 容器没有启动,但 docker 整个都安装在本地磁盘上,它肯定能支持在磁盘上找到其对应位置直接修改文件。
虽然 docker 容器无法启动,但是docker inspect
命令依然可以使用,我们利用这个命令找到它的一些执行信息,其中就有 GraphDriver 的相关信息:
"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
里找到程序进行修改。