Docker的数据管理


layout: post
title: Docker的数据管理
date: 2018-11-06 15:13:36
categories: Docker
catalog: true
tags:
- Volume


我们知道容器中的任何修改默认都是不会被保存的。想要保存容器运行时产生的数据,我们需要使用Volume数据卷技术来提供独立于容器外的持久化存储,它也可以提供容器与容器之前的共享数据。简单来说我感觉就是挂载,把本地磁盘中的某个目录挂载到容器中的某个目录,这样容器对这个目录的任何操作相当与操作我们本地的相应目录。

这里有三种方式使用Volume进行容器的持久存储。

从容器挂载

[root@HJWDEV docker]# docker run -d --name nginx-fun -v /usr/share/nginx/html nginx-fun

--name 指定容器名

-v 需要挂载的目录

上述命令是创建一个名为nginx-fun容器并加载 数据卷 到容器的 /usr/share/nginx/html 目录。也就是把我们本地的某个目录挂载到容器中的 /usr/share/nginx/html 目录中,具体是我们本地的哪个目录不需要我们指定。这也是为了保证Docker的可移植性,因为不是每个宿主机上都有对应的目录。

[root@HJWDEV docker]# docker inspect nginx-fun

通过上述命令我们可以知道使用的是本地的哪个目录,找到如下信息:

"Mounts": [
            {
                "Type": "volume",
                "Name": "388f5df2b08fa24b75358acdccf41ac987971b5c9edb02c693b4bfd8929a09fb",
                "Source": "/var/lib/docker/volumes/388f5df2b08fa24b75358acdccf41ac987971b5c9edb02c693b4bfd8929a09fb/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]

可以看到Source 指向的地址就是我们本地对应的目录,我们可以进入这个目录查看:

[root@HJWDEV docker]# cd /var/lib/docker/volumes/388f5df2b08fa24b75358acdccf41ac987971b5c9edb02c693b4bfd8929a09fb/_data
[root@HJWDEV _data]# ll
总用量 8
-rw-r--r--. 1 root root 494 9月  25 23:04 50x.html
-rw-r--r--. 1 root root  54 9月  26 10:53 index.html

可以看到目录中有两个文件,是nginx-fun容器中/usr/share/nginx/html目录的默认文件。

[root@HJWDEV _data]# cat index.html
<html>
<body>
<h2>Docker is Fun!</h2>
</body>
</html>
[root@HJWDEV _data]# vi index.html

我们查看index.html中的默认内容并修改成如下内容:

<html>
<body>
<h2>Docker is Fun!</h2>
<h3>Docker is interesing</h3>
</body>
</html>

接着进入容器中的/usr/share/nginx/html目录,看文件是否被修改:

[root@HJWDEV _data]# docker exec -it nginx-fun /bin/bash
root@15f556dcc7e5:/# cd /usr/share/nginx/html
root@15f556dcc7e5:/usr/share/nginx/html# ls
50x.html  index.html
root@15f556dcc7e5:/usr/share/nginx/html# cat index.html 
<html>
<body>
<h2>Docker is Fun!</h2>
<h3>Docker is interesing</h3>
</body>
</html>
root@15f556dcc7e5:/usr/share/nginx/html#

可以看到容器中的文件也同步修改了。同样的如果容器中/usr/share/nginx/html 中的文件被修改了,宿主机中的对应目录文件也会跟着变动

这种方式虽然实现了数据的持久存储,但要查询宿主机中挂载的目录比较麻烦,下面这种方式则可以直接指定宿主机中的需要挂载的目录。

从宿主机挂载

挂载目录

[root@HJWDEV docker]# touch volume/index.html
[root@HJWDEV docker]# vi volume/index.html

首页我们在docker/volume 目录新建一个index.html文件,写入以下内容:

this is volume

接着启动一个nginx容器

[root@HJWDEV docker]# docker run -p 80:80 -d -v $PWD/volume:/usr/share/nginx/html nginx-fun

$PWD 表示当前目录路径

上面的命令把宿主机的$PWD/volume 目录挂载到容器中的 /usr/share/nginx/html 目录。$PWD/volume目录必须使用绝对路径且是存在的,不然会报错。

访问nginx的首页:

[root@HJWDEV docker]# curl http://localhost/
this is volume

可以看到输出的内容就是我们宿主机挂载目录中的index.html的内容。

[root@HJWDEV docker]# vi volume/index.htm

我们重新修改一下宿主机挂载目录下的index.html文件,修改如下:

this is volume,is cool!

我们直接进入容器内查看 /usr/share/nginx/html目录中的index.html是否同步被修改:

[root@HJWDEV docker]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
a3aad9e00870        nginx-fun           "nginx -g 'daemon of…"   13 minutes ago      Up 13 minutes       0.0.0.0:80->80/tcp   nostalgic_booth
[root@HJWDEV docker]# docker exec -it a3aad9e00870 /bin/bash
root@a3aad9e00870:/# cd /usr/share/nginx/html
root@a3aad9e00870:/usr/share/nginx/html# ls
index.html
root@a3aad9e00870:/usr/share/nginx/html# cat index.html
this is volume,is cool!

可以看到容器中的文件也同步被修改了。


挂载文件

还有一种方式是把宿主机的一个文件挂载到容器中。

[root@HJWDEV docker]# docker run --rm -it -v $PWD/volume/bash_history.txt:/root/.bash_history nginx-fun /bin/bash
root@6b22a51db2ee:/# cd /usr/share/nginx/html
root@6b22a51db2ee:/usr/share/nginx/html# ls
50x.html  index.html
root@6b22a51db2ee:/usr/share/nginx/html# exit
exit
[root@HJWDEV docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@HJWDEV docker]# cat volume/bash_history.txt 
cd /usr/share/nginx/html
ls
cat index.html
exit

--rm 表示退出进程后自动删除容器,可以看到第5 行中exit后再 docker ps 显示没有运行的容器了

-it 分配一个伪终端并打开交互模式

上述命令把宿主机中的$PWD/volume/bash_history.txt 文件挂载到容器中的 /root/.bash_history 文件。 /root/.bash_history 文件中记录的是容器内使用命令的历史记录,因此容器中使用过的命令同样也会写入宿主机的$PWD/volume/bash_history.txt 文件中。

共享数据卷容器

如果有一些持续更新的数据需要在容器之间共享,我们可以使用数据卷容器。数据卷容器 其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载。

[root@HJWDEV docker]# docker run -it -v /opt/dbdata --name dbdata ubuntu /bin/bash
root@3842c0845e26:/# cd /opt/dbdata
root@3842c0845e26:/opt/dbdata# touch db.properties
root@3842c0845e26:/opt/dbdata# exit

通过上述命令我们创建一个数据卷容器,在容器的/opt/dbdata 目录创建一个新文件 db.properties

通过 docker inspect 命令查看容器挂载的宿主机目录:

[root@HJWDEV docker]# docker inspect dbdata

可以看到宿主机的目录如下:

"Mounts": [
            {
                "Type": "volume",
                "Name": "01eb6e6a162ece43abc601783805d89a0a0e871cf7c612bad28e1858ae7606f8",
                "Source": "/var/lib/docker/volumes/01eb6e6a162ece43abc601783805d89a0a0e871cf7c612bad28e1858ae7606f8/_data",
                "Destination": "/opt/dbdata",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]

再创建一个名为vol_a 的容器并通过 --volumes-from 命令挂载 dbdata 容器 。进入vol_a 容器查看/opt/dbdata 目录可以看到存在 dbdata 容器中创建的文件,如下:

[root@HJWDEV docker]# docker run -it --name vol_a --volumes-from dbdata ubuntu /bin/bash
root@90f972394243:/# cd /opt/dbdata/
root@90f972394243:/opt/dbdata# ls
db.properties

如挂载源有多个,可以使用多次--volumes-from

这样即实现了容器间的数据共享。

删除数据卷

如果创建容器时挂载了volume,会在类似 /var/lib/docker/volumes/01eb6e6a162ece43abc601783805d89a0a0e871cf7c612bad28e1858ae7606f8/_data 目录下会生成相应的文件(路径,不同版本,不同操作系统会有所不同,具体可以用docker inspect查看容器具体信息),当删除容器时,宿主机上的挂载目录时不会删除的,并且目录名称是随机字符,不知意义,所以在删除容器时,需要妥善处理容器的volume。删除容器时一并删除volume有二种方法:

方式一

[root@HJWDEV docker]# docker rm -v dbdata
dbdata
[root@HJWDEV docker]# cd /var/lib/docker/volumes/01eb6e6a162ece43abc601783805d89a0a0e871cf7c612bad28e1858ae7606f8/_data
[root@HJWDEV _data]#

使用docker rm-v 参数 删除容器时会一并把 volume 删除,但这里发现目录还是存在,因为我们上面的vol_a 容器还在使用 dbdata 的挂载。所以需要把vol_a 也删除。

[root@HJWDEV docker]# docker rm -v vol_a
vol_a
[root@HJWDEV docker]# cd /var/lib/docker/volumes/01eb6e6a162ece43abc601783805d89a0a0e871cf7c612bad28e1858ae7606f8/_data
-bash: cd: /var/lib/docker/volumes/01eb6e6a162ece43abc601783805d89a0a0e871cf7c612bad28e1858ae7606f8/_data: 没有那个文件或目录
[root@HJWDEV docker]# 

这样 volume 的目录也会被删除了。

方式二

docker run --rm 

启动容器的时候加了 -rm 参数,这样在容器停止后自动删除容器以及容器所挂载的volume 。这种方式上挂载文件 这一节已经使用过。

你可能感兴趣的:(Docker)