正确commit mysql容器
前言
接手了两个 Docker 容器,一个是 MySQL 的容器,一个是 Tomcat 容器,里面是一些 Demo 程序和一些测试数据,需要将其 Commit 成镜像方便部署,所以有了下文。
本篇文章会解决以下问题:
- docker commit 提交后镜像的大小为什么不会变化?
commit tomcat 容器
Tomcat 容器很顺利,使用 docker commit 5a2831dc52c8 tomcat_change:v1
命令直接提交就好了,Tomcat 容器相比 Tomcat 镜像只是拷贝了项目到容器中,并没有进行其他操作,只是省略了通过 Dockerfile 重新构建的过程。
1 | b@ubuntu20:~$ docker commit 5a2831dc52c8 tomcat_change:v1 |
可以看到,新的 Tomcat 镜像相比原来的镜像大了好多,多出来的这部分内容就是 Tomcat 中的项目文件所占的大小。
commit MySQL 容器
但是在 commit MySQL 时,出现了问题,不论我怎么 commit,新生成的镜像大小都不会变化,哪怕 1M 的变化都没有。
1 | b@ubuntu20:~$ docker commit aa3fcc421465 mysql_change:v1 |
可以看到,新生成的 MySQL 镜像还是原来的大小,按理说 MySQL 在初次启动时会初始化数据库的,而且我也将数据库导入进去了,不可能一点空间都不占用。
我将新生成的镜像 save 后拷贝出来,找到了 MySQL 数据文件默认位置,在 /var/lib/mysql
这个目录,但是这个目录是空的,也就是说数据文件根本没有被保存到这个镜像中,这就奇怪了。
Google 没有查询到类似的问题,我去查询了 docker commit 的官方文档,其中有这么一句话:
The commit operation will not include any data contained in volumes mounted inside the container.
意思是说 commit 命令不会包含挂载在容器中的卷中的数据。我大概明白了什么,去 Docker Hub 上查看了 MySQL 对应版本的 Dockerfile,其中有这么一句:VOLUME /var/lib/mysql
,也就是说 MySQL 容器在启动时自动挂载了一个卷到 /var/lib/mysql
目录中,数据文件全部写入到了这个卷中,通过 docker volume ls
命令查看系统中存在的卷:
1 | b@ubuntu20:~$ docker volume ls |
果真有一个卷,使用 docker volume inspect 54f2937cefd8cda5f91580579fb99e0a87a9b39bebfa0d4b2da3f993917b793e
命令查看卷的详细信息:
1 | b@ubuntu20:~$ docker volume inspect 54f2937cefd8cda5f91580579fb99e0a87a9b39bebfa0d4b2da3f993917b793e |
Mountpoint 字段提示了我们卷在系统中的具体位置,查看文件夹中的内容:
1 | root@ubuntu20:/home/b# cd /var/lib/docker/volumes/54f2937cefd8cda5f91580579fb99e0a87a9b39bebfa0d4b2da3f993917b793e/_data |
熟悉的 MySQL 数据文件找到了。
问题原因
总结下出现问题的原因:因为在 Dockerfile 文件中有一条 VOLUME /var/lib/mysql
命令,指定了卷挂载的位置,所以在每次生成 MySQL 容器时 Dockers 都会新建一个名字为哈希值的卷,挂载到 Volume 命令指定的位置,这样就可以将指定位置的内容全部写入到卷中,防止往 Docker 容器中写入大量内容导致性能问题。再结合官方文档中的 commit 命令不会包含挂载在容器中的卷中的数据,所以在 commit MySQL 容器时,卷中的数据被忽略了,导致我 commit 出来的镜像的数据文件夹是空的。
解决方法
解决方法很简单,新建一个 MySQL 容器,然后更改 MySQL 的配置文件中的数据文件路径,更改为和 /var/lib/mysql
不一样即可,重新启动 MySQL 容器,数据文件就会被写入到新的文件夹中了,然后删除之前新建的卷即可,重新 commit ,问题解决。
不过不推荐使用这种方法,因为我这里是一个 Demo 数据库,基本上只有读没有写,而且对数据可靠性也不敏感,所以选择了最简单的 commit 命令来完成。
总结
由于对 MySQL 镜像和 Docker 的卷不了解,导致了在使用时出现这个问题,看来还是要多学习。
同时官方文档中还提到了:
it is better to use Dockerfiles to manage your images in a documented and maintainable way.
最好通过 Dockerfile 以文档化和可维护的方式来管理镜像。就是说如果有更改最好体现在 Dockerfile 中,然后重新编译,因为可以通过历史提交来追踪镜像的变化,如果直接 commit 的话不便于其他人了解镜像中被更改了什么。
本文章首发于个人博客 LLLibra146’s blog
本文作者:LLLibra146
更多文章请关注:
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!
本文链接:
https://blog.d77.xyz/archives/b59689bb.html