1. 什么是容器数据卷。
Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,
那么当容器删除后,数据自然也就没有了。为了能保存数据在docker中我们使用卷。
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
数据卷的特点:
1:数据卷可在容器之间共享或重用数据。
2:卷中的更改可以直接生效。
3:数据卷中的更改不会包含在镜像的更新中。
4:数据卷的生命周期一直持续到没有容器使用它为止。
总结:数据卷的作用。容器的持久化、容器间继承+共享数据。
2. 添加数据卷(也就是映射目录)。
命令如下:也就是运行镜像,并且使用-v参数,把容器的目录和宿主机的目录进行绑定。
docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
例子:运行centos镜像,并且把容器的/containerDataVolume目录和宿主机的/myDataVolume进行绑定同步。
docker run -it -v /myDataVolume:/containerDataVolume centos
说明:
- 如果不存在指定的目录,那么会创建/containerDataVolume和/myDataVolume目录。
- 修改宿主机或容器的目录内容,对应另一方的目录都会修改。是一个双向的数据同步。
- 如果把容器stop,修改宿主机的目录内容,当重启容器之后,修改的内容会马上同步到容器对应的目录/containerDataVolume。
3. 只读映射。
命令如下:
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
上面的ro是readonly,表示运行容器后,容器内的目录是只读的。也就是宿主机可以读写宿主机这边对应的目录,但是容器内的对应目录不能读写。例子如下:
docker run -it -v /myDataVolume:/containerDataVolume:ro centos
上面的命令启动容器后,宿主机这边的目录/myDataVolume修改后会同步到容器的目录/containerDataVolume,但是进入容器后并不能修改容器的目录/containerDataVolume。因为定义了容器内的目录是只读的。
4. 用Dockerfile添加数据卷。
- Dockerfile是什么:
Dockerfile 就是描述docker镜像的一个文件。根据Dockerfile可以使用docker build 命令生成一个新的镜像。可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷。
- -v 主机目录:容器目录 这种目录映射方式,不能在Dockerfile中实现:
docker是运行在宿主机上的,不能保证宿主机都有某个特定的目录。所以出于可移植和分享的考虑,用 -v 主机目录:容器目录 这种方法不能够直接在Dockerfile中实现。
- dockerfile添加数据卷的例子:
一、新建一个文件名字随意(一般就叫Dockerfile)。内容如下:
# volume test
FROM centos
VOLUME ["/containerDataVolume1","/containerDataVolume2"]
CMD echo "finished,--------success1"
CMD /bin/bash
上面的文件内容中:
- FROM centos 表示即将创建的镜像是从centos继承过来的。
- VOLUME ["/containerDataVolume1","/containerDataVolume2"] 表示在新的镜像里面创建2个数据卷/containerDataVolume1和/containerDataVolume2。
- CMD echo "finished,--------success1" 表示输出finished,--------success1。
- CMD /bin/bash 表示打开bash终端。
二、使用docker build 根据Dockerfile创建镜像。
创建镜像的命令如下:
docker build -f Dockerfile文件的位置 -t 新的镜像名 .
- -f :指定要使用的Dockerfile文件的位置;
--tag, -t:镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
命令最后还有一个点。
运行如下命令,就创建一个名字是wk/centos的镜像。使用的Dockerfile是/root/Dockerfile。
[root@localhost ~]# docker build -f /root/Dockerfile -t wk/centos .
Sending build context to Docker daemon 38.97MB
Step 1/4 : FROM centos
---> 1e1148e4cc2c
Step 2/4 : VOLUME ["/containerDataVolume1","/containerDataVolume2"]
---> [Warning] IPv4 forwarding is disabled. Networking will not work.
---> Running in ad1055634422
Removing intermediate container ad1055634422
---> dbeb2f24458b
Step 3/4 : CMD echo "finished,--------success1"
---> [Warning] IPv4 forwarding is disabled. Networking will not work.
---> Running in de271419c5af
Removing intermediate container de271419c5af
---> eacb86752e4e
Step 4/4 : CMD /bin/bash
---> [Warning] IPv4 forwarding is disabled. Networking will not work.
---> Running in 00bde01e437c
Removing intermediate container 00bde01e437c
---> f700fad120f8
Successfully built f700fad120f8
Successfully tagged wk/centos:latest
使用docker images 可以看到刚刚创建好的镜像。
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wk/centos latest f700fad120f8 About a minute ago 202MB
运行刚刚创建的镜像wk/centos,进入这个centos容器后可以看到创建了文件目录containerDataVolume1和containerDataVolume2
[root@localhost ~]# docker run -it wk/centos
WARNING: IPv4 forwarding is disabled. Networking will not work.
[root@37aa7d20e166 /]# ll
total 12
-rw-r--r--. 1 root root 12076 Dec 5 01:37 anaconda-post.log
lrwxrwxrwx. 1 root root 7 Dec 5 01:36 bin -> usr/bin
drwxr-xr-x. 2 root root 6 Mar 13 02:38 containerDataVolume1
drwxr-xr-x. 2 root root 6 Mar 13 02:38 containerDataVolume2
退出容器后,使用 docker inspect 容器ID 可以看到下面Mounts的内容。在Source、Destination可以看到容器的目录和宿主机的哪个目录映射。Source、Destination 对应的目录是同步的,修改其中一个另一个也会同步。
"Mounts": [
{
"Type": "volume",
"Name": "ff9ef0ac17ea2bf3fe83a241a4bc7eba661472149e1e227d40ba7f4cf2844860",
"Source": "/var/lib/docker/volumes/ff9ef0ac17ea2bf3fe83a241a4bc7eba661472149e1e227d40ba7f4cf2844860/_data",
"Destination": "/containerDataVolume1",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "a59169b80b6c94436bba25048214a1228754af082efaec5765e962a0bb472cf2",
"Source": "/var/lib/docker/volumes/a59169b80b6c94436bba25048214a1228754af082efaec5765e962a0bb472cf2/_data",
"Destination": "/containerDataVolume2",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
5. 容器卷的继承。容器之间数据共享。
在运行容器的时候,类似于一种继承关系。子容器的数据卷会继承父容器的数据卷。孙容器的数据卷也会继承爷爷辈。也就是父、子、孙容器中的数据卷目录映射到宿主机的同一个目录。
测试例子如下:接着上面用Dockfile创建的镜像wk/centos。
- 运行一个容器,取名testParent。
docker run -it --name testParent wk/centos
- 运行一个容器,取名testChild。并使用 --volumes-from testParent 指定这个容器的数据卷继承testParent的数据卷。
docker run -it --name testChild --volumes-from testParent wk/centos
- 运行一个容器,取名testGrandson。并使用 --volumes-from testChild 指定这个容器的数据卷继承testChild的数据卷。
docker run -it --name testGrandson --volumes-from testChild wk/centos
- 使用docker inspect 分别查看上面这3个容器的信息。
docker inspect testParent
docker inspect testChild
docker inspect testGrandson
Mounts下面可以看到它们的数据卷的name是一样的,容器内的路径映射到宿主机Source下的路径也是一样的。修改其中任何容器的对应目录下的数据,都会在其他容器中看到。修改宿主机的映射目录,也可以同步到每个容器。这就是--volumes-from 参数的作用。可以使得容器的映射目录相同。可以多个容器共享数据。
"Mounts": [
{
"Type": "volume",
"Name": "3ff95763b7a8cee196b0a794e60145c055c565bfb6ea85c414dfd9098cbb4521",
"Source": "/var/lib/docker/volumes/3ff95763b7a8cee196b0a794e60145c055c565bfb6ea85c414dfd9098cbb4521/_data",
"Destination": "/containerDataVolume1",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "6e34389e99bf6c32ea4bac213f838d59fe367101127af6cd950952c380bd4201",
"Source": "/var/lib/docker/volumes/6e34389e99bf6c32ea4bac213f838d59fe367101127af6cd950952c380bd4201/_data",
"Destination": "/containerDataVolume2",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],