【Docker】容器挂载文件修改后 Commit 新镜像,挂载文件不会更新
- 问题描述:
- 场景验证
- 1. 自定义镜像 Dockerfile
- 2. 创建 hello.txt 文件:
- 3. 构建自定义镜像
- 4. 运行镜像,并检查容器内部文件内容
- 5. 新增挂载目录,并修改,验证 Commit 的新镜像
- 总结
- 1. docker commit 时不会抓取容器挂载的文件系统;
- 2. 解决办法
- 2.1 直接在 Dockerfile 中更新文件:
- 2.2 将文件复制到容器并重新构建
问题描述:
在使用某个镜像的时候,由于需要频繁修改镜像中的某些文件,于是就将这些文件所在的文件夹挂载到宿主机上了,在需要更新的时候,直接更新宿主机上挂载的目录下的文件来达到更新容器中的文件。
上面的骚操作,看似没什么问题,实际也是正常可用的。
最多是修改完挂载路径下面的文件,然后重启一下容器,修改就生效了,省时省力,不用重新构建镜像了。
但是在需要打版本,更新成新的镜像时,问题就暴露出来了,Commit 的新镜像发现某个路径下面的文件竟然不是最新的。
如果不是特意瞅一眼新镜像内挂载目录下的文件的时间,这打着新版本旗号的镜像,里子却是旧的文件,如果没有发现,那么可能在某个阳光明媚的午后,一回头,一颗子弹正中眉心。。。。。
场景验证
1. 自定义镜像 Dockerfile
创建一个自定义镜像,并让它持续运行,Dockerfile 内容如下:
步骤说明
- FROM busybox:latest: 使用 busybox:latest 作为基础镜像。
- RUN mkdir -p /data: 在容器内创建 /data 目录。
- COPY hello.txt /data/hello.txt: 将宿主机上的 hello.txt 文件复制到容器的 /data 目录。请确保在构建镜像的目录中存在 hello.txt 文件。
- CMD [“sh”, “-c”, “while true; do sleep 3600; done”]: 设置容器启动后执行的命令,使容器持续运行,每小时休眠一次。
2. 创建 hello.txt 文件:
在与 Dockerfile 相同的目录中,创建一个 hello.txt
文件,添加一些内容:
3. 构建自定义镜像
在 Dockerfile 所在目录中运行以下命令来构建镜像:
可以看到,构建了一个新的镜像,并且在镜像里面预置了自定义了一个文件;
4. 运行镜像,并检查容器内部文件内容
新建 docker-compose.yaml
文件,内容如下:
第一次运行,查看预置文件内容时,先不挂载目录,直接运行:
进入容器内部,查看预置文件内容:
可以看到,当前镜像运行的容器,确实是我们之前构建镜像时的文件内容;
5. 新增挂载目录,并修改,验证 Commit 的新镜像
在当前目录下新建文件夹,并新增一个同名文件,来覆盖容器内的文件:
打开上面 docker-compose.yaml
文件中的注释,新的内容如下:
保存后,再次启动:
为了保险起见,我这里先删除了旧的容器,然后启动新的容器;
再次进入容器内查看 /data/hello.txt
文件内容:
可以看到,在挂载目录之后,容器内的同名文件确实被覆盖了,并且在宿主机上修改,容器内也是实时生效的。
接着验证 Commit 新镜像:
这里将当前已经挂载了的容器 Commit 成一个新的镜像,镜像为:my_custom_busybox:1.0.1
修改 docker-compose.yaml
文件中的镜像版本为my_custom_busybox:1.0.1
,然后重新启动容器,再次进入容器内查看文件内容:
发现文件内容还是原来构建镜像时的内容;
总结
1. docker commit 时不会抓取容器挂载的文件系统;
在 Docker
中,容器挂载的文件系统变化不会影响到通过 docker commit
创建的新镜像,因为 docker commit
只会保存容器的层,而不会保存挂载点的内容。
2. 解决办法
2.1 直接在 Dockerfile 中更新文件:
修改 Dockerfile,然后重新构建镜像。这种方式最直接,可以确保所有更改都被纳入到新的镜像中。
使用 docker build 构建镜像:docker build -t my_updated_image .
2.2 将文件复制到容器并重新构建
通过 docker cp 将文件从宿主机复制到运行中的容器中,然后使用 docker commit 创建新镜像。这种方法会包含手动修改后的文件。