docker挂载数据卷的行为和解决docker数据卷丢失的问题

再也不用担心数据卷不翼而飞了

docker的本意就是只作为容器存在,任何配置或重要文件都应该以挂载的方式存在,像mysql,redis这种专门用来做数据库存储的容器,本身只提供了服务,真正的数据库数据并不在容器内,而是以docker的volume数据卷的方式存在。

执行docker volume ls看到我的电脑上当前存在的数据卷列表,目前我只运行了一个本地的redis

1
2
DRIVER              VOLUME NAME
local               5c44cbef81c711c3b10ca64f79a7cb733655c05dc8949ab6005d44f103002a5f

此时我拉去一个mysql镜像并运行,顺便创建了一个test数据库,再次执行如下所示

1
2
3
4
DRIVER              VOLUME NAME
local               20265b8be590fcef965a1fa8e544d3cd1c1424330abd86e81445839fb6516de0
local               5c44cbef81c711c3b10ca64f79a7cb733655c05dc8949ab6005d44f103002a5f
local               f0042fac97c7c21710fd2a0e71306f7e34336fc30ac9b3f86e560edea32f0353

docker inspect mysql查看容器信息会发现这样的挂载形式,为了看清区别,我在启动mysql容器时额外挂在了一个普通文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
"Mounts": [
            {
                "Type": "bind",
                "Source": "/usr/share/zoneinfo/Asia/Shanghai",
                "Destination": "/etc/localtime",
                "Mode": "ro",
                "RW": false,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",
                "Name": "20265b8be590fcef965a1fa8e544d3cd1c1424330abd86e81445839fb6516de0",
                "Source": "/var/lib/docker/volumes/20265b8be590fcef965a1fa8e544d3cd1c1424330abd86e81445839fb6516de0/_data",
                "Destination": "/var/lib/mysql",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

看得出普通的挂载type类型是bind,而数据卷的type类型是volume,且它就存在于宿主机中,source就是它的路径,可以cd进去看一下数据卷里都有什么

可以看到我之前创建的test数据库在这里是以文件夹方式存在的,进入文件夹发现只有一个db.opt配置文件,因为此时数据库是空的。为了看看数据是如何存放在数据卷中的,我随便建了个表并插入数据

create table a(a int); insert into a values(1);

此时再回到数据卷test目录,多出两个以表名命名的文件,上网查了一下这两种后缀是InnoDB引擎的存储方式

而以上都不是本文的重点。。只是顺便满足下好奇心,我想说的重点是在某种情况下,比如你发现当初运行mysql容器时忘记把配置文件挂载出来,此时不论你用docker原始的方式还是修改docker-compose之后up -d,都会让容器内的数据丢失,因为最终都是要执行删除容器并重新启动一个新容器,所以会自动创建一个新的数据卷,所以我想知道如何在这种情况下把原来的数据卷挂载回去,这样不论如何删除,都使用同一个数据卷,就不会有数据丢失的问题了。

本以为很麻烦,其实答案就是上面那个docker inspect mysql输出的容器信息里。里面明确地声明了把宿主机中的数据卷挂载到了容器中的/var/lib/mysql位置

1
2
  "Source": "/var/lib/docker/volumes/20265b8be590fcef965a1fa8e544d3cd1c1424330abd86e81445839fb6516de0/_data",
                "Destination": "/var/lib/mysql",

所以我们面临两种情况:

  • 当初不清楚也没考虑这么多,所以使用的是默认分类的数据卷,也就是上文遇到的问题,此时只需要再删除并重建容器时,把原来的数据卷位置以相同的方式挂载即可

docker run -it -v /var/lib/docker/volumes/20265b8be590fcef965a1fa8e544d3cd1c1424330abd86e81445839fb6516de0/_data:/var/lib/mysql mysql

唯一的不同就是现在的挂载类型type由volume变成了bind

  • 另一种情况就是知道这种默认行为,并在一开始就不使用默认数据卷,而是直接挂载在某处,比如

docker run -it -v /home/shingle/mysql/data/:/var/lib/mysql mysql

或者可以先创建一个带名字的数据卷,可以直接挂载使用

1
2
3
  volumes:
    mysql-data:
      driver: local
1
2
  volumes:
        - version-data:/var/lib/mysql

两种方式各有好处和弊端,使用默认的数据卷更方便docker进行管理,比如docker volume prune会移除所有没被使用的数据卷,而自行挂载则需要先看到该镜像的文档,查找数据卷应该被挂载到哪里(比如mysql的/var/lib/mysql),在以后不用的时候还需要手动删除。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值