基础 6 —— Docker 容器数据卷

基础 6 —— Docker 容器数据卷 6.1 数据卷的基本概念还记得我们上节课运行私有参库容器的命令吗[rootshjava101 ~]# docker run -d -p 5000:5000 -v /krisswen/myregistry/:/tmp/registry --privilegedtrue registryc2759846ce33fe3f57f48ccc747158e9aa4bb354517de0da9b0f3d42f8fb0549现在疑问来了这个 -v 参数是什么意思就是实现数据卷的挂载。我们以上面这个命令为例/krisswen/myregistry/定义的是宿主机的目录该目录如果不存在会被自动创建。/tmp/registry容器内部的数据目录。–privilegedtrue必须要加上否则数据卷挂载失败。因为 CentOS7 安全模块会比之前系统版本加强不安全的会先禁止所以目录挂载的情况被默认为不安全的行为在 SELinux 里面挂载目录被禁止掉了如果要开启我们一般使用 --privilegedtrue 命令扩大容器的权限解决挂载目录没有权限的问题也即使用该参数container 内的 root 拥有真正的 root 权限否则container 内的 root 只是外部的一个普通用户权限。那什么是容器卷?容器卷就是目录或文件存在于一个或多个容器中由 docker 挂载到容器但不属于联合文件系统因此能够绕过 Union File System 提供一些用于持续存储或共享数据的特性。卷的设计目的就是数据的持久化完全独立于容器的生存周期因此 Docker 不会在容器删除时删除其挂载的数据卷。一句话数据卷有点类似我们 Redis 里面的 rdb 和 aof 文件。数据卷能干嘛?Docker 容器产生的数据如果不备份那么当容器实例删除后容器内的数据自然也就没有了。为了能保存数据在 Docker 中我们使用卷。数据卷的特点1数据卷可在容器之间共享或重用数据2卷中的更改可以直接实时生效3数据卷中的更改不会包含在镜像的更新中4数据卷的生命周期一直持续到没有容器使用它为止6.2 数据卷的基本案例我们还是以 Ubuntu 容器为例在宿主机和容器之间添加数据卷。添加数据卷的命令是:docker run -it --privilegedtrue -v /宿主机绝对路径目录:/容器内目录 镜像名[rootshjava101 ~]# docker run -it --privilegedtrue -v /tmp/hostData:/tmp/dockerData1 ubuntu /bin/bash此时我们查看宿主机目录[rootshjava101 /]# cd /tmp[rootshjava101 hostData]# pwd/tmp/hostData我们发现宿主机之前不存在的目录现在已经自动创建了。我们再看看容器中的目录:root1c88215ff319:/# cd /tmp/dockerData1/root1c88215ff319:/tmp/dockerData1# lltotal0这个目录也没有问题。现在我们在宿主机对应的目录里面创建一个文件。[rootshjava101 hostData]# touch a.txt我们回到容器目录查看root1c88215ff319:/tmp/dockerData1# lsa.txt我们发现在容器中这个文件也会存在。接下来我们在容器中再创建一个文件root1c88215ff319:/tmp/dockerData1# touch b.txt我们回到宿主机查看[rootshjava101 hostData]# lltotal0-rw-r--r--.1root root0Dec2516:51 a.txt -rw-r--r--.1root root0Dec2516:52 b.txt我们发现只要宿主机和容器之间的目录形成挂载关系不管是容器内数据发生变化还是宿主机内部数据发生变化都会被另一方即时同步如果我们把容器停止掉然后在宿主机修改数据呢[rootshjava101 ~]# docker stop 1c88215ff319 # 停止容器1c88215ff319我们在宿主机对应的目录里面再创建一个文件。[rootshjava101 hostData]# touch c.txt我们再次启动容器进入对应目录查看文件:[rootshjava101 ~]# docker exec -it 1c88215ff319 /bin/bashroot1c88215ff319:/# cd /tmp/dockerData1/root1c88215ff319:/tmp/dockerData1# lltotal0drwxr-xr-x.2root root45Dec2508:58 ./ drwxrwxrwt.1root root25Dec2508:47../ -rw-r--r--.1root root0Dec2508:51 a.txt -rw-r--r--.1root root0Dec2508:52 b.txt -rw-r--r--.1root root0Dec2508:58 c.txt我们发现即使容器停止了当再次启动容器之后文件依然还是可以同步。查看据卷是否挂载成功docker inspect 容器id[rootshjava101 ~]# docker inspect 1c88215ff319注意上面的挂载默认在容器内部的目录都可以进行读写操作。如果我们只想在容器内部进行读操作呢? 我们需要加上:ro 标识[rootshjava101 ~]# docker run -it --privilegedtrue -v /tmp/hostData:/tmp/dockerData1:ro ubuntu /bin/bashrootf4bce15fcc4e:/# cd /tmp/dockerData1/rootf4bce15fcc4e:/tmp/dockerData1# touch d.txt # 创建文件失败touch: cannottouchd.txt:Read-onlyfilesystem此时如果宿主机写入内容可以同步给容器内容器可以读取到。容器的数据卷还可以被继承和共享。我们先启动一个 Ubuntu 的容器 1[rootshjava101 ~]# docker run -it --privilegedtrue -v /tmp/hostData:/tmp/data --nameu1 ubuntu /bin/bashrootf3f75fcb55d4:/#我们再启动容器 2 继承容器 1 的卷规则语法格式docker run -it --privilegedtrue --volumes-from 父类 --name u2 ubuntu[rootshjava101 hostData]# docker run -it --privilegedtrue --volumes-from u1 --nameu2 ubuntu /bin/bashroot1e8776ef5733:/# cd /tmp/data/root1e8776ef5733:/tmp/data#我们发现容器 2 有和容器 1 一样的数据卷因为容器 1 的数据卷目录被容器 2 继承了。我们在容器 1 里面定义一个文件:rootf3f75fcb55d4:/# cd /tmp/data/rootf3f75fcb55d4:/# touch abc.txt我们在容器 2 里面查看这个文件root1e8776ef5733:/tmp/data# lltotal0drwxr-xr-x.2root root60Dec2509:29 ./ drwxrwxrwt.1root root18Dec2509:25../ -rw-r--r--.1root root0Dec2509:29 abc.txt我们发现容器 2 也存在这个文件了这样我们就实现了不同容器之间的数据共享。