Docker共享数据

上一篇所说的volume卷就是共享数据的关键,比如web集群,集群每一台节点的数据都要求是相同的,包括之前的一些服务时,也为web集群部署nfs后端来存放数据

bind mount共享数据

学过的bind mount可以用来实现共享数据,但是方法比较笨拙,只能是创建容器的时候指定挂载目录,这样就需要一台一台去进行创建指定

如下:

创建一个要共享的页面目录

[root@localhost ~]# mkdir htdocs/
[root@localhost ~]# vim htdocs/index.html
nihao

然后进行bind mount的方式共享数据

[root@localhost ~]# docker run -d -p 80 --name web --volume /root/htdocs/:/usr/local/apahce2/htdocs httpd
2ac16608128f2ac9462cbded6b0a92b1c210d9c34d7a56278b3b4f6e64e400d9
[root@localhost ~]# docker run -d -p 80 --name web1 --volume /root/htdocs/:/usr/local/apahce2/htdocs httpd
5f2f8214a377541f2c35512bdd241c43d356e32a052bc6a9d683124412b77ea2
[root@localhost ~]# docker run -d -p 80 --name web2 --volume /root/htdocs/:/usr/local/apahce2/htdocs httpd
a51b1477241634d0f66e51c4a7d3d6595128cc30f98c4c70732ed60e6fd92cc8
[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                   NAMES
a51b14772416        httpd               "httpd-foreground"   9 seconds ago       Up 8 seconds        0.0.0.0:32770->80/tcp   web2
5f2f8214a377        httpd               "httpd-foreground"   14 seconds ago      Up 14 seconds       0.0.0.0:32769->80/tcp   web1
2ac16608128f        httpd               "httpd-foreground"   25 seconds ago      Up 24 seconds       0.0.0.0:32768->80/tcp   web
# 分别访问不同容器映射到主机的端口
[root@localhost ~]# curl 192.168.1.11:32770
nihao
[root@localhost ~]# curl 192.168.1.11:32769
nihao
[root@localhost ~]# curl 192.168.1.11:32768
nihao

也可以发现这样确实很麻烦

卷容器共享数据

volume container:专门为其他容器提供volume的容器

volume container既可以通过bind mount共享数据库,也可以通过manage volume来共享数据

我们可以去创建一个卷容器(volume container)名为vc_data,它可以用来指定多个--volume

如下:

[root@localhost ~]# docker create --name vc_data --volume /root/htdocs/:/usr/local/apache2/htdocs \
--volume test:/usr/local/apache2/logs busybox
139ec94bf4cc9dc9198e831ac4ff6e39b166d38c7bda2b3993a35130e59ab975

--volume /root/htdocs/:/usr/local/apache2/htdocs:将本地的htdocs目录以bind mount方式挂载到容器中的htdocs目录中

--volume test:/usr/local/apache2/logs:将容器中的logs目录以manage volume的方式映射到物理机本地,volume 名为test

执行完以上命令就会看到一个容器,name为vc_data,这就是我们创建好的volume container。

[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                   NAMES
139ec94bf4cc        busybox             "sh"                 4 minutes ago       Created                                     vc_data
a51b14772416        httpd               "httpd-foreground"   11 minutes ago      Up 11 minutes       0.0.0.0:32770->80/tcp   web2
5f2f8214a377        httpd               "httpd-foreground"   11 minutes ago      Up 11 minutes       0.0.0.0:32769->80/tcp   web1
2ac16608128f        httpd               "httpd-foreground"   12 minutes ago      Up 12 minutes       0.0.0.0:32768->80/tcp   web

查看volume id

[root@localhost ~]# docker volume ls
DRIVER              VOLUME NAME
local               test

查看容器信息中的挂载信息

[root@localhost ~]# docker inspect vc_data 
# 找到以下关键信息
        "Mounts": [
            {
                "Type": "bind",  # bind mount 共享数据
                "Source": "/root/htdocs",
                "Destination": "/usr/local/apache2/htdocs",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",  # manage volume共享数据
                "Name": "test",
                "Source": "/var/lib/docker/volumes/test/_data",
                "Destination": "/usr/local/apache2/logs",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

可以看到两种共享数据的方法共存在了vc_data容器中

将volume container被其他容器使用

使用--volumes-from参数指定volume container(vc_data),可以很大程度避免指定目录时,写错目录名,这些容器都将具有两个挂载类型

[root@localhost ~]# docker run -d -p 80 --volumes-from vc_data --name web3 httpd
0e352478964ac86658db8e72f796bd188f2f269dbdaf41f69816df94c06ee0b7
[root@localhost ~]# docker run -d -p 80 --volumes-from vc_data --name web4 httpd
e966b5860bfd9f063e541791adaeef59b01f4c5595ff7462d5cad3d8ccb1e6bd
[root@localhost ~]# docker run -d -p 80 --volumes-from vc_data --name web5 httpd
390ac7c88206d4c56c1c4dcc7ac9ecda877fcc0587920fe25ffc15a39ef59efc

查看web3/4/5映射端口

[root@localhost ~]# docker ps
PORTS                   NAMES
0.0.0.0:32773->80/tcp   web5
0.0.0.0:32772->80/tcp   web4
0.0.0.0:32771->80/tcp   web3
0.0.0.0:32770->80/tcp   web2
0.0.0.0:32769->80/tcp   web1
0.0.0.0:32768->80/tcp   web

访问验证

[root@localhost ~]# curl 192.168.1.11:32771
nihao
[root@localhost ~]# curl 192.168.1.11:32772
nihao
[root@localhost ~]# curl 192.168.1.11:32773
nihao

volume container 的特点

  1. 与 bind mount 相比,不必为每一个容器指定 host path,所有 path 都在 volume container 中定义好了,容器只需与 volume container 关联,实现了容器与 host 的解耦
  2. 使用 volume container 的容器其 mount point 是一致的,有利于配置的规范和标准化,但也带来一定的局限,使用时需要综合考虑。

观察起来的话volume container也是有缺点的,就是在物理机中必须存在原始数据。如果要去直接挂载一个空目录来挂载的话,NFS最合适不过了

NFS挂载共享数据

将NFS中的目录共享出去,docker的所有容器来使用这个共享目录就可以了

启动另一台服务器,用来做NFS服务器(192.168.1.12)

192.168.1.12

安装NFS

[root@localhost ~]# yum -y install nfs-utils rpcbind

创建共享目录

[root@localhost ~]# mkdir -p /data/nfs/docker

将目录写入共享文件

[root@localhost ~]# vim /etc/exports
/data/nfs/ *(rw,no_root_squash,sync)
[root@localhost ~]# exportfs -r
[root@localhost ~]# systemctl start rpcbind nfs-server
[root@localhost ~]# systemctl enable rpcbind nfs-server

192.168.1.11

验证共享

[root@localhost ~]# showmount -e 192.168.1.12
Export list for 192.168.1.12:
/data/nfs *

使用docker创建驱动类型为nfs的磁盘volume-nfs,并指定该nfs的ip,共享目录的权限,以及共享目录

[root@localhost ~]# docker volume create --driver local \
--opt type=nfs --opt o=addr=192.168.1.12,rw \
--opt device=:/data/nfs volume-nfs
volume-nfs
# 参数解释
--driver , -d    local    # 指定卷驱动程序名称,local为默认
--name        # 指定卷名
--opt , -o        # 设置驱动程序特定选项

查看创建好的volume

[root@localhost ~]# docker volume ls
DRIVER              VOLUME NAME
local               volume-nfs

查看该volume的信息

[root@localhost ~]# docker volume inspect volume-nfs 
[
    {
        "CreatedAt": "2020-03-31T21:07:36+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/volume-nfs/_data",
        # volume-fs的挂载点
        "Name": "volume-nfs",
        "Options": {
            "device": "/data/nfs", # nfs共享目录
            "o": "addr=192.168.1.12,rw", # nfs服务器地址
            "type": "nfs"  # 驱动类型
        },
        "Scope": "local"
    }
]

使用volume-nfs来运行容器

[root@localhost ~]# docker run -itd --name bbox1 --volume volume-nfs:/nfs busybox
[root@localhost ~]# docker exec -it bbox1 /bin/sh
/ # cd /nfs/docker/
/nfs/docker # ls
/nfs/docker # echo "hello world" > 123
/nfs/docker # ls
123

然后查看nfs服务器共享目录的变化(192.168.1.12)

[root@localhost ~]# cd /data/nfs/docker/
[root@localhost docker]# ls
123

同样在nfs创建文件或者目录也会同步到容器中

查看容器挂载点的数据存放的位置的命令

[root@localhost ~]# docker inspect -f {{.Mounts}} bbox1
[{volume volume-nfs /var/lib/docker/volumes/volume-nfs/_data /nfs local z true }]

查看挂载情况

[root@localhost ~]# df -h | grep /data/nfs
:/data/nfs   46G  5.7G   40G  13% /var/lib/docker/volumes/volume-nfs/_data

Dockerfile—VOLUME

data-packed volume container:数据存放到镜像中随便迁移

最后一种共享数据的方法就是,之前有提到过在Dockerfile中的VOLUME可以在构建镜像的时候将物理机的目录挂载到镜像中,使用镜像实例化容器之后,可以直接使用目录中的内容

清空之前实验的容器,方便去查看

编写Dockerfile

[root@localhost ~]# vim Dockerfile
FROM busybox
ADD htdocs /usr/local/apache2/htdocs  # 将htdocs中的内容复制到镜像中的指定目录
VOLUME packed /usr/local/apache2/htdocs
# 将镜像中的指定目录以manage volume的方式挂载到物理机中,命名卷名为packed

构建镜像

[root@localhost ~]#  docker build -t datapacked /root
Sending build context to Docker daemon    6.9MB
Step 1/3 : FROM busybox
 ---> 83aa35aa1c79
Step 2/3 : ADD htdocs /usr/local/apache2/htdocs
 ---> 0a49920ed469
Step 3/3 : VOLUME packed /usr/local/apache2/htdocs
 ---> Running in 170bb0363ede
Removing intermediate container 170bb0363ede
 ---> 18031b1fdc1d
Successfully built 18031b1fdc1d
Successfully tagged datapacked:latest

创建一个容器但不运行,使用刚构建的镜像

[root@localhost ~]# docker create --name vc_data datapacked
34ec4accf29c70f4daa2875c35769d30d2ecb5bfe6ce2dd2e8f38a36dc894d1e

再使用httpd镜像实例化容器,也做到了共享资源

[root@localhost ~]# docker run -d -p 80:80 --volumes-from vc_data httpd
9a0705b631dc8e785dc43b9eece8d4feb792b0a367aa7bfd6d8ce5966db75521
[root@localhost ~]# curl 192.168.1.11
nihao

共享数据方法总结

docker共享数据

bind mount:从物理机挂载到容器内

managed volume:从容器内挂载到物理机的volume

volume container:创建一个容器,在创建的时候可以使用bind mount也可以使用managed volume,其他容器使用时,可以使用--volumes-from来使用该volume container

NFS:共享目录,在docker中创建volume并挂载共享目录,然后运行的容器使用--volume指定该卷即可

Dockerfile:将数据使用VOLUME写入到镜像中,然后迁移数据时,直接pull下载镜像就可以运行容器使用以前的数据了

评论




正在载入...
PoweredHexo
HostedAliyun
DNSAliyun
ThemeVolantis
UV
PV
BY-NC-SA 4.0