docker容器互联实现目录、服务共享 docker学习笔记18:Dockerfile 指令 VOLUME 介绍

一、需求

docker使服务之间实现容器隔离,比如Javaweb项目前端、后端、数据库、数据库后台,分别把它们部署在不同的容器里面,实现隔离。但服务和服务之间也有互访的需求,这就涉及到容器网络和容器互联挂载访问机制的内容。

容器是基于镜像创建的,最后的容器文件系统包括镜像的只读层+可写层,容器中的进程操作的数据持久化都是保存在容器的可写层上。一旦容器删除后,这些数据就没了,除非我们人工备份下来(或者基于容器创建新的镜像)。能否可以让容器进程持久化的数据保存在主机上呢?这样即使容器删除了,数据还在。

docker本身提供了一种机制,可以将主机上的某个目录与容器的某个目录(称为挂载点、或者叫卷)关联起来,容器上的挂载点下的内容就是主机的这个目录下的内容,这类似linux系统下mount的机制。 这样的话,我们修改主机上该目录的内容时,不需要同步容器,对容器来说是立即生效的。挂载点可以让多个容器共享。

二、通过docker run命令

 1、运行命令:

 # docker run --name node1 -h nodex -v /home/upload/:/data -d -i -t centos /bin/bash

其中的 -v 标记 在容器中设置了一个挂载点 /data(就是容器中的一个目录),并将主机上的 /home/upload/ 目录中的内容关联到 /data下。

这样在容器中对/data目录下的操作,还是在主机上对/home/upload/的操作,都是完全实时同步的,因为这两个目录实际都是指向主机目录。

通过docker inspect 命令查看目录对应关系

# docker inspect node1

[
    {
        "Id": "d1c5d9eb3838c724b597db428ce26e72cfc667fbefb0ed712dbbaef5f374070f",
.............................
 "Mounts": [
            {
                "Type": "bind",
                "Source": "/home/upload",
                "Destination": "/data",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
...........................

2、运行命令:

# docker run --name node2 -h nodex -v /data -d -i -t centos /bin/bash

上面-v的标记只设置了容器的挂载点,并没有指定关联的主机目录。这时docker会自动绑定主机上的一个目录。通过docker inspect 命令可以查看到。

# docker inspect node2

[
    {
        "Id": "d1c5d9eb3838c724b597db428ce26e72cfc667fbefb0ed712dbbaef5f374070f",
.............................
"Mounts": [
            {
                "Type": "volume",
                "Name": "d04353ed38845a54a2bd5909b82c470fe644391626f877644e9580aba22a3a12",
                "Source": "/var/lib/docker/volumes/d04353ed38845a54a2bd5909b82c470fe644391626f877644e9580aba22a3a12/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...........................

上面 Mounts下的每条信息记录了容器上一个挂载点的信息,"Destination" 值是容器的挂载点,"Source"值是对应的主机目录。

可以看出这种方式对应的主机目录是自动创建的,其目的不是让在主机上修改,而是让多个容器共享。

三、通过dockerfile创建挂载点

上面介绍的通过docker run命令的-v标识创建的挂载点只能对创建的容器有效。

通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点。

还有一个区别是,通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。

# cat Dockerfile

下面的dockfile文件通过VOLUME指令指定了两个挂载点 /data1 和 /data2

#test
FROM centos
MAINTAINER djl
VOLUME ["/data1","/data2"]

# docker build -t test .

[root@localhost ~]# docker build -t test .
Sending build context to Docker daemon 28.77 MB
Step 1/3 : FROM centos
 ---> 9f38484d220f
Step 2/3 : MAINTAINER djl
 ---> Running in d14672dadf87
 ---> 602a4b8e796d
Removing intermediate container d14672dadf87
Step 3/3 : VOLUME /data1 /data2
 ---> Running in 30b586d5aaf4
 ---> f51b774e7869
Removing intermediate container 30b586d5aaf4
Successfully built f51b774e7869

查看构建的镜像

# docker images

[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test                latest              f51b774e7869        2 minutes ago       202 MB
centos              latest              9f38484d220f        4 months ago        202 MB

运行一个容器

# docker run --name node3 -h nodex -d -i -t test /bin/bash

[root@localhost ~]# docker run --name node3 -h nodex -d -i -t test /bin/bash
6fb05f94a368e05dd96e2f42432f1e4c0dcad1bd6b726079c69fba0625783c38
[root@localhost ~]#
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6fb05f94a368        test                "/bin/bash"         8 seconds ago       Up 7 seconds                            node3
f2bf65a82acc        centos              "/bin/bash"         About an hour ago   Up About an hour                        node1
d1c5d9eb3838        centos              "/bin/bash"         2 hours ago         Up 2 hours                              node2

我们通过docker inspect 查看通过该dockerfile创建的镜像生成的容器,可以看到如下信息

# docker inspect node3

[
    {
        "Id": "d1c5d9eb3838c724b597db428ce26e72cfc667fbefb0ed712dbbaef5f374070f",
.............................
"Mounts": [
            {
                "Type": "volume",
                "Name": "cc2fcaccae2dca5021d82d4d581e1f500816a96745237527d4fa7925a2061e04",
                "Source": "/var/lib/docker/volumes/cc2fcaccae2dca5021d82d4d581e1f500816a96745237527d4fa7925a2061e04/_data",
                "Destination": "/data1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "2f7419b960ae0a3f7be58875f5021312b181fdad72e2c7390b2bb7aab7d06b24",
                "Source": "/var/lib/docker/volumes/2f7419b960ae0a3f7be58875f5021312b181fdad72e2c7390b2bb7aab7d06b24/_data",
                "Destination": "/data2",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...........................

可以看到两个挂载点的信息。

四、容器共享卷(挂载点)

 下面我们创建另一个容器可以和node3共享 /data1 和 /data2卷 ,这是在 docker run中使用 --volumes-from标记,如:

1、可以是来源不同镜像,如:

# docker run --name node4 -itd --volumes-from node3 centos /bin/bash

[root@localhost ~]# docker run --name node4 -itd --volumes-from node3 centos /bin/bash
ced022f71608c81fd2d689861809b033996351e4dc23c210eaeda675ff28a31b
[root@localhost ~]#
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
ced022f71608        centos              "/bin/bash"         3 seconds ago       Up 2 seconds                            node4
6fb05f94a368        test                "/bin/bash"         12 minutes ago      Up 12 minutes                           node3
f2bf65a82acc        centos              "/bin/bash"         2 hours ago         Up 2 hours                              node1
d1c5d9eb3838        centos              "/bin/bash"         2 hours ago         Up 2 hours                              node2

验证:

[root@localhost ~]# docker exec node3 ls /
anaconda-post.log
bin
data1
data2
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
[root@localhost ~]# docker exec node4 ls /
anaconda-post.log
bin
data1
data2
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

2、也可以是同一镜像,如:

# docker run --name node5 -itd --volumes-from node3 test /bin/bash

[root@localhost ~]# docker run --name node5 -itd --volumes-from node3 test /bin/bash
e6a2584eab2cce5b678f432d8eb48a762e5b1b2d57bcd76ee48f121c51ff282d
[root@localhost ~]#
[root@localhost ~]# docker exec node5 ls /
anaconda-post.log
bin
data1
data2
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

五、最佳实践:数据容器

如果多个容器需要共享数据(如持久化数据库、配置文件或者数据文件等),可以考虑创建一个特定的数据容器,该容器有1个或多个卷。

其它容器通过--volumes-from 来共享这个数据容器的卷。

因为容器的卷本质上对应主机上的目录,所以这个数据容器也不需要启动。

# docker run --name dbdata test echo "data container"

[root@localhost ~]# docker run --name dbdata test echo "data container"
data container
[root@localhost ~]#
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
ac04a4f5d1ab        test                "echo 'data contai..."   9 seconds ago       Exited (0) 9 seconds ago                       dbdata
e6a2584eab2c        test                "/bin/bash"              8 minutes ago       Up 8 minutes                                   node5
ced022f71608        centos              "/bin/bash"              16 minutes ago      Up 16 minutes                                  node4
6fb05f94a368        test                "/bin/bash"              28 minutes ago      Up 28 minutes                                  node3
f2bf65a82acc        centos              "/bin/bash"              2 hours ago         Up 2 hours                                     node1
d1c5d9eb3838        centos              "/bin/bash"              3 hours ago         Up 3 hours                                     node2
[root@localhost ~]# docker start dbdata
dbdata
[root@localhost ~]#
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
ac04a4f5d1ab        test                "echo 'data contai..."   58 seconds ago      Exited (0) 4 seconds ago                       dbdata
e6a2584eab2c        test                "/bin/bash"              9 minutes ago       Up 9 minutes                                   node5
ced022f71608        centos              "/bin/bash"              16 minutes ago      Up 16 minutes                                  node4
6fb05f94a368        test                "/bin/bash"              29 minutes ago      Up 29 minutes                                  node3
f2bf65a82acc        centos              "/bin/bash"              2 hours ago         Up 2 hours                                     node1
d1c5d9eb3838        centos              "/bin/bash"              3 hours ago         Up 3 hours                                     node2

说明:有个卷,容器之间的数据共享比较方便,但也有很多问题需要解决,如权限控制、数据的备份、卷的删除等。

参考博客:

docker学习笔记18:Dockerfile 指令 VOLUME 介绍

猜你喜欢

转载自www.cnblogs.com/djlsunshine/p/11284463.html
今日推荐