问题描述:
最近在使用docker部署mysql时,在持久化mysql数据时遇到了一个有趣的问题:下载一个mysql镜像后,使用docker启动这个镜像后,成功创建一个mysql的镜像
docker run 命令启动mysql容器:
成功启动后,可以直接进入mysql交互界面,使用创建镜像时创建的root用户密码进入mysql数据库
之后使用root用户创建了两个数据库,然后使用建表语句创建了几张表,并且插入了几条数据。这时,我想把目前为止对mysql容器做的变更保存下来,所以就想到了使用docker commit指令
docker commit 命令会将docker容器的变更保存下来,并且生成新的镜像。生成新的镜像后,我想看看之前创建的库和表还在不在,就使用新的镜像创建了新的容器mysqlnew,并且进入容器查看mysql情况,神奇的现象出现了,mysql中竟然是空的,我们创建的表也消失了。
原因分析:
查阅了docker commit的官方文档说明后,发现了在扩展说明中有这么一句话:
意思是commit操作并不会包含容器内挂载数据卷中的数据变化。通过docker inspect mysql 命令查看该镜像的详细内容
这说明了这个容器将容器内的/var/lib/mysql路径作为volume挂载。查看容器内的该路径发现的确是mysql数据库的数据文件,这点在mysql的dockerHub主页也能发现
这么说就说得通了,虽然文件的确是发生了变化,但是由于文件是在容器挂载的数据卷中,所以这些变化没有被commit,所以新构建的容器中不会存在这些库,表以及数据。
解决方案:
我们可以通过docker提供的数据挂载来实现。
volume是由docker默认及推荐的挂载方式,volume由docker直接管理,同一个volume可以共享给多个容器使用,volume和容器的生命周期完全独立,容器删除时volume仍然存在,除非使用docker volume相应命令删除volume。
已经有一个容器使用了volume,想把volume里的数据在新的容器中使用bind mount方式挂载该怎么办呢?我们可以先把mysql容器中所需要的文件拷贝出来到本地的/var/docker/mysql,通过
然后在创建新的mysql容器时,挂载该文件即可
这时可以再次查看新的mysql容器中的详情
挂载文件成功,打开数据库之后,发现创建的库表信息都存在。这样新的容器就可以保留mysqldock中的数据了,问题解决!