木灵鱼儿

木灵鱼儿

阅读:661

最后更新:2022/02/20/ 21:41:37

docker 容器数据卷使用

什么是容器数据卷

其作用就是方便容器与外部宿主机的文件交互,毕竟容器可以重启启动一个,但是数据只有一份啊,所以如果能将数据存在宿主机上,容器随便换,宿主机本身再定时备份,问题不就解决了。

作用

卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性:

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

特点

  1. 数据卷可在容器之间共享或重用数据
  2. 卷中的更改可以直接生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!

创建一个数据卷 方式1:在容器中使用命令添加

docker run -it -v [宿主机的绝对目录]:[容器目录] [镜像名] 

-it表示交互模式,-v则是挂载卷。

这里以启动centos并挂载它的home目录到windows的桌面上

# 运行后会有一个弹窗提示,允许就完事了
 docker run -it -v C:/Users/13219/Desktop/home:/home centos

# 我们查看容器home下文件
[root@7dd013e9eec7 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@7dd013e9eec7 /]# cd home
[root@7dd013e9eec7 home]# ls

# home下是空的,于是我们创建一个文件
[root@7dd013e9eec7 home]# touch test.js      # 此时去桌面的home文件夹下,就会有一个test.js文件

查看元数据判断是否挂载成功

docker inspect 7dd013e9eec7

# 查看 Mounts 配置
"Mounts": [
  {
    "Type": "bind",
    "Source": "C:/Users/13219/Desktop/home",
    "Destination": "/home",
    "Mode": "",
    "RW": true,
    "Propagation": "rprivate"
  }
],

可以看到挂载配置已经存在了,说明挂载成功。

当我们关闭容器后,挂载的卷数据依旧存在,我们修改后,再启动镜像,数据会同步更新。

实战:安装mysql

mysql的数据一般是两个,一个配置,一个数据库数据,目录分别为:

  1. /etc/mysql/conf.d 配置
  2. /var/lib/mysql 数据库数据

mysql还有一个需求,就是它需要设置管理员密码,这个配置可以再docker的mysql镜像的文档中找到,官方有这么一段命令:

docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

其中-e是设置环境变量,后面是设置管理员密码的配置,我们照着搞一下就行了

docker run -d -p 3310:3306 --name mysql1 -v C:/Users/13219/Desktop/mysql/conf:/etc/mysql/conf.d -v C:/Users/13219/Desktop/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

启动后我们使用数据库管理软件连接一下,因为我们的是3310端口

我们可以创建一个数据库看看数据两边是否都同步了。

测试数据库数据是否同步

首先通过数据库管理软件创建一个test的数据库,当然名字自定都行,测试而已

# 进入镜像
docker exec -it 2b2345f26f09 /bin/bash

# 进入数据库数据目录
cd /var/lib/mysql

# 查看文件
ls
auto.cnf    client-cert.pem  ib_logfile0  ibtmp1              private_key.pem  server-key.pem
ca-key.pem  client-key.pem   ib_logfile1  mysql               public_key.pem   sys
ca.pem      ib_buffer_pool   ibdata1      performance_schema  server-cert.pem  test

可以看到末尾出现了一个test目录,查看挂载的卷,也同样存在一个test目录

即便此时我们删除容器,挂载到宿主机的卷是不会消失的。

docker rmi 2b2345f26f09 

匿名挂载和具名挂载

匿名挂载

挂载时只写容器内的路径

docker run -d -P --name nginx2 -v /etc/nginx nginx

启动后我们通过volume命令查看卷

docker volume --help

create      Create a volume    # 创建一个卷
inspect     Display detailed information on one or more volumes    # 显示一个或多个卷的详细信息
ls          List volumes    # 列出所有卷
prune       Remove all unused local volumes    # 移除未使用的卷
rm          Remove one or more volumes         # 移除一个或多个卷
# 列出所有的卷
docker volume ls

local     380c014be9e1b4a71ac3c75e9eedf97d5271b6dd48369474b6fb8a2011f79d0b

这个就是我们刚刚匿名挂载的卷

查看详情

docker volume inspect 380c014be9e1b4a71ac3c75e9eedf97d5271b6dd48369474b6fb8a2011f79d0b

# 返回
[
    {
        "CreatedAt": "2022-02-17T16:20:04Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/380c014be9e1b4a71ac3c75e9eedf97d5271b6dd48369474b6fb8a2011f79d0b/_data",
        "Name": "380c014be9e1b4a71ac3c75e9eedf97d5271b6dd48369474b6fb8a2011f79d0b",
        "Options": null,
        "Scope": "local"
    }
]

可以看到一些详细信息,其中Mountpoint是docker的默认卷挂载的位置,匿名卷和具名卷都会挂载在这,但是再windows中,这个路径并不正确,可能真实的卷被重新映射了,目前没找到,有机会再找找看。

具名挂载

具名挂载相对于匿名挂载,就是多加了个名字,加了名字就方便识别

docker run -d -P --name nginx3 -v [名字]:/etc/nginx nginx

例子

docker run -d -P --name nginx3 -v testnginx:/etc/nginx nginx

# 挂载后通过volume查看
docker volume ls

DRIVER    VOLUME NAME
local     380c014be9e1b4a71ac3c75e9eedf97d5271b6dd48369474b6fb8a2011f79d0b
local     testnginx

# 再查看详情
docker volume inspect testnginx

[
    {
        "CreatedAt": "2022-02-17T16:37:53Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/testnginx/_data",
        "Name": "testnginx",
        "Options": null,
        "Scope": "local"
    }
]

:ro和:rw

有些时候我们可以看到一些特殊的挂载

docker run -d -P --name nginx4 -v testnginx:/etc/nginx:ro nginx
docker run -d -P --name nginx4 -v testnginx:/etc/nginx:rw nginx

:ro

表示卷挂载后容器只能读取,但是宿主机可以读写,意思是英文:readonly的缩写

:rw

表示容器可以读写,宿主机也可以读写,意思是英文:readwrite的缩写

所以,只要是ro了,说明这个卷只能宿主机来操作,容器无权限,而默认值则是:rw

创建一个数据卷 方式2:Dockerfile

dockerfile的方式也可以创建数据卷,我们创建一个dockerfile文件,没有后缀格式的。

FROM centos:latest   # 指定系统镜像
VOLUME [ "volume1", "volume2" ]  # 创建两个数据卷
CMD echo "---end---"  # 创建完毕输出end
CMD /bin/bash  # 进入镜像时默认进入bash

配置文件创建好了,我们可以使用build命令打包生成一个我们自己的镜像

docker build -f [dockerfile文件路径名] -t [创建的镜像名]:[tag] .   # 注意有一个.

如果添加了tag,那么运行镜像的时候也需要加上tag,负责会运行失败

例子

docker build -f C:\Users\13219\Desktop\dockerfile -t text/centos:1.0 .

# 输出
[+] Building 0.1s (5/5) FINISHED
...
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

此时镜像就生成好了, 可以通过docker images 查看生成的镜像

docker images

REPOSITORY                               TAG       IMAGE ID       CREATED         SIZE
text/centos                              1.0       975574ebd7e4   5 months ago    231MB

运行一下,查看创建的数据卷是否成功

docker run -it text/centos:1.0 /bin/bash   # 如果名字会有重复,记得带上tag

# 查看目录
ls
bin  etc   lib    lost+found  mnt  proc  run   srv  tmp  var      volume2
dev  home  lib64  media       opt  root  sbin  sys  usr  volume1

可以看到我们创建的volume2volume1数据卷。

查看容器的详情

docker inspect b0357514757c

# 查看Mounts

"Mounts": [
  {
    "Type": "volume",
    "Name": "bc907f2bdaf56cdc3976bf0623a075336ca62b0ec464d5ba8e0fd6b162231188",
    "Source": "/var/lib/docker/volumes/bc907f2bdaf56cdc3976bf0623a075336ca62b0ec464d5ba8e0fd6b162231188/_data",
    "Destination": "volume1",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "80639f696c9887efa68e7a8ee4b0a047d36ea153eed891c205b2a7ed61939970",
    "Source": "/var/lib/docker/volumes/80639f696c9887efa68e7a8ee4b0a047d36ea153eed891c205b2a7ed61939970/_data",
    "Destination": "volume2",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
],

可以发现我们创建的卷是一个匿名的卷。我们可以通过Source的路径查看主机上docker的卷,但是由于是windows,目前没法直接像linux那样访问这个路径。

数据卷容器

当多个容器之间需要数据沟通的时候,就可以使用数据卷容器,数据卷容器就是创建了数据卷的容器,它作为一个数据交互的容器,其他的容器通过--volumes-from继承这个数据卷容器,然后就可以再目录中存在数据卷容器创建的数据卷。

需要注意的是,这个不是映射,而是一个拷贝,当数据卷容器被删除或者停止时,继承于它的容器们之间相互依旧可以继续沟通,文件数据也得以保存。

--volumes-from [镜像id或者镜像name]

例子

# 创建一个数据卷容器
docker run  -it --name boxss text/centos:1.0 /bin/bash  # 启动之前创建的镜像

# 查看容器id或者名字
docker ps
c90b419e7698   text/centos:1.0   "/bin/bash"   2 minutes ago    Up 2 minutes              boxss

# 创建一个容器1并继承数据卷容器
docker run -it --name ex1 --volumes-from c90b419e7698 centos /bin/bash
# 查看目录
ls
bin  etc   lib    lost+found  mnt  proc  run   srv  tmp  var      volume2
dev  home  lib64  media       opt  root  sbin  sys  usr  volume1

可以看到ex1中也存在了volume1、volume2。并且镜像可以是不同的镜像。

在创建一个容器2

docker run -it --name ex2 --volumes-from c90b419e7698 centos /bin/bash
# 查看目录
ls
bin  etc   lib    lost+found  mnt  proc  run   srv  tmp  var      volume2
dev  home  lib64  media       opt  root  sbin  sys  usr  volume1

当我们在容器1再volume1、volume2目录下增删改的时候,容器2也会同步数据。

当数据卷容器删除后,容器1和容器2的数据已经保持关联,文件也不会被删除。

我们甚至可以在创建容器3时继承容器1或者容器2,他们之间也可以创建关联。

版权申明

本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。

关于作者

站点职位 博主
获得点赞 0
文章被阅读 661

相关文章