文章目录

  • 前言
  • 什么是数据卷
  • 创建数据卷
  • 绑定数据卷
  • 创建共享数据卷容器
  • 删除共享数据卷


前言

当我们启动容器后会产生各种数据,这些数据都存放在容器内,一旦不小心执行了docker rm 命令就会删容器导致数据丢失,在生产环境中必须对docker容器产生的数据进行持久化,而且也会涉及到多个容器数据共享的问题。为了解决上述问题我们可以使用docker的 数据卷技术

什么是数据卷

数据卷(Data Volumes)是一个可供容器使用的特殊目录,通过这个目录可以将容器内的数据直接映射到宿主机上,即使不小心删除了容器,容器产生的数据也保存在了宿主机上了。比如我可以将容器路径 /usr/local/data 映射到宿主机 /soft/docker/data路径上,如下图所示:

docker 数据分析 docker swarm 数据卷_centos


通过数据卷技术我们可以完成 容器数据的持久化容器之间的数据共享

创建数据卷

docker提供了 volume 命令用于管理数据卷,我们可以使用 help查看命令的使用帮助:

[root@VM-0-10-centos ~]# docker volume --help

Usage:  docker volume COMMAND

Manage volumes

Commands:
 create      Create a volume
 inspect     Display detailed information on one or more volumes
 ls          List volumes
 prune       Remove all unused local volumes
 rm          Remove one or more volumes

Run 'docker volume COMMAND --help' for more information on a command.

使用create命令可以创建一个容器卷如下所示:

[root@VM-0-10-centos ~]# docker volume create my-volume
my-volume

使用ls命令可以查看当前容器存在的所有卷:

[root@VM-0-10-centos ~]# docker volume ls
DRIVER    VOLUME NAME
local     my-volume

create命令创建的卷默认在 宿主机 /var/lib/docker/volumes路径下,可以使用 tree 命令查看:

[root@VM-0-10-centos volumes]# tree /var/lib/docker/volumes/
/var/lib/docker/volumes/
|-- backingFsBlockDev
|-- metadata.db
`-- my-volume
    `-- _data

2 directories, 2 files

使用inspect命令可以查看数据卷详情:

[root@VM-0-10-centos volumes]# docker volume inspect my-volume
[
    {
        "CreatedAt": "2021-12-25T21:22:14+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
        "Name": "my-volume",
        "Options": {},
        "Scope": "local"
    }
]

使用prune命令清理无用的容器:

[root@VM-0-10-centos volumes]# docker volume prune 
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
my-volume

Total reclaimed space: 0B

使用rm命令删除容器卷:

  • 创建容器
## 创建容器卷
[root@VM-0-10-centos volumes]# docker volume create my-volume
my-volume
## 列出所有的容器卷
[root@VM-0-10-centos volumes]# docker volume ls
DRIVER    VOLUME NAME
local     my-volume

使用 -q 可以只列出容器卷名称:

[root@VM-0-10-centos volumes]# docker volume ls -q
my-volume

删除单个容器卷:

[root@VM-0-10-centos volumes]# docker volume rm my-volume
 my-volume

批量删除所有容器卷

[root@VM-0-10-centos volumes]# docker volume create my-volume
my-volume
## 删除所有容器卷
[root@VM-0-10-centos volumes]# docker volume ls -q | xargs docker volume rm
my-volume

绑定数据卷

上面我们使用 volume命令来管理数据卷外,还可以在创建容器时创建容器卷并同时建立起容器卷与宿主机路径的映射,首先我们下载一个nginx的镜像来演示容器卷的绑定:

  1. 下载nginx镜像
[root@VM-0-10-centos volumes]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete 
f3409a9a9e73: Pull complete 
9919a6cbae9c: Pull complete 
fc1ce43285d7: Pull complete 
1f01ab499216: Pull complete 
13cfaf79ff6d: Pull complete 
Digest: sha256:366e9f1ddebdb844044c2fafd13b75271a9f620819370f8971220c2b330a9254
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
  1. 运行镜像并挂载数据卷

可以在创建容器的时候可以建立宿主机路径与容器内容器的映射:例如映射nginx容器的html目录:例如映射宿主机路径 /soft/data/docker/html/soft/nginx/html

[root@VM-0-10-centos html]# docker run -d --name nginx -P -v /soft/data/docker/html:/soft/nginx/html nginx
e0c7ed8c9999b4121c3c3a62eb23f7579a145ecbbc3885ecfe461fad1a8842cc

创建test.html:

vim test.html
## 添加如下内容:
<<html>
<head>
<script type="text/javascript">
function alertIndex()
{
var x=document.getElementById("mySelect").selectedIndex;
var y=document.getElementsByTagName("option");
alert(y[x].text + " has the index of: " + y[x].index);
}
</script>
</head>
<body>

<form>
Select your favorite fruit:
<select id="mySelect">
  <option>Apple</option>
  <option>Orange</option>
  <option>Pineapple</option>
  <option>Banana</option>
</select>
<br />
<br />
<input type="button" onclick="alertIndex()"
value="Show index of the chosen fruit">
</form>

</body>
</html>

可以查看当前路径下有test.html

[root@VM-0-10-centos html]# ll
total 4
-rw-r--r-- 1 root root 555 Dec 26 20:03 test.html
[root@VM-0-10-centos html]# pwd
/soft/data/docker/html

进入容器查看:

[root@VM-0-10-centos html]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0c7ed8c9999   nginx     "/docker-entrypoint.…"   46 minutes ago   Up 46 minutes   0.0.0.0:49160->80/tcp, :::49160->80/tcp   nginx

进入容器后可以查看到刚刚在主机上创建的html文件,在容器相应的路径上也存在。

[root@VM-0-10-centos html]# docker exec -it nginx /bin/bash
## 可以看到/soft/nginx/html
root@e0c7ed8c9999:/# cd /soft/nginx/html
root@e0c7ed8c9999:/soft/nginx/html# ls -lsa
total 12
4 drwxr-xr-x 2 root root 4096 Dec 26 12:03 .
4 drwxr-xr-x 3 root root 4096 Dec 26 11:19 ..
4 -rw-r--r-- 1 root root  555 Dec 26 12:03 test.html

将刚刚创建的test.html复制到 /usr/share/nginx/html/

root@e0c7ed8c9999:/soft/nginx/html# cp test.html /usr/share/nginx/html/

然后在浏览器进行访问如下所示:

docker 数据分析 docker swarm 数据卷_容器_02


上面挂载容器卷的命令是 -v,也可以使用 –mount命令:

[root@VM-0-10-centos ~]# docker run -d --name my-nginx -P --mount type=bind,source=/soft/data/docker/my-nginx,destination=/soft/container/nginx nginx
docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /soft/data/docker/my-nginx.
See 'docker run --help'.

需要注意的是宿主机挂载的路径必须存在否则会报错如上所示:

[root@VM-0-10-centos ~]# mkdir -p /soft/data/docker/my-nginx
[root@VM-0-10-centos ~]# docker run -d --name my-nginx -P --mount type=bind,source=/soft/data/docker/my-nginx,destination=/soft/container/nginx nginx
bdf701f0a0835089e408d750381684f74ab8393f708cfc0678c4b6b3e21e5254

登录nginx容器查看路径映射是否存在。

[root@VM-0-10-centos ~]# docker exec -it my-nginx /bin/bash
root@bdf701f0a083:/# cd /soft/container/nginx/
root@bdf701f0a083:/soft/container/nginx# ls -lsa
total 8
4 drwxr-xr-x 2 root root 4096 Dec 26 14:23 .
4 drwxr-xr-x 3 root root 4096 Dec 26 14:23 ..

容器内创建文档:

root@bdf701f0a083:/soft/container/nginx# echo "test message" > haha.txt
root@bdf701f0a083:/soft/container/nginx# ls -lsa
total 12
4 drwxr-xr-x 2 root root 4096 Dec 26 14:29 .
4 drwxr-xr-x 3 root root 4096 Dec 26 14:23 ..
4 -rw-r--r-- 1 root root   13 Dec 26 14:29 haha.txt

宿主机查看文本内容:

[root@VM-0-10-centos ~]# cat /soft/data/docker/my-nginx/haha.txt 
test message

需要注意的是宿主机的路径必须为绝对路径,使用-- mount 需要确定挂载的路径存在否则会出错,Docker在挂载主机目录的时候也可以指定目录的读写权限,默认权限是读写(rw),用户也可以指定只读权限即 ro

docker run -d --name my-nginx -P --mount type=bind,source=/soft/data/docker/my-nginx:ro,destination=/soft/container/nginx nginx

加了 ro权限后,容器只能对挂载的路径进行进行读取,无法修改数据卷内的数据。

创建共享数据卷容器

一般在开发中往往会遇到多个容器直接共享同一批数据,可以使用 数据卷容器,需要注意的是数据卷容器本身也是一个容器 ,下面以三个centos镜像为例演示容器数据卷的使用:

  1. 下载centos镜像:
[root@VM-0-10-centos ~]# docker pull centos:7
7: Pulling from library/centos
2d473b07cdd5: Pull complete 
Digest: sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987
Status: Downloaded newer image for centos:7
docker.io/library/centos:7

创建一个数据卷容器

[root@VM-0-10-centos ~]# docker run -it -v /dir --name dir centos:7

docker 数据分析 docker swarm 数据卷_docker 数据分析_03


dir目录中新建一个文件并输入内容:

[root@8d3d2d3d6edf /]# echo "Hi I am GalenGao" > /dir/test.txt

使用 crtl + p + q

创建容器centos1中查看是否存在对应的容器卷目录:

[root@VM-0-10-centos volumes]# docker run -it --name centos1 --volumes-from dir centos:7

docker 数据分析 docker swarm 数据卷_docker_04


可以清晰看到对应的 dir目录存在且test.txt文档也存在,这个时候我们追加一些文本内容:

[root@6cc32c0aeb05 dir]# echo "it's a message from centos1"  >> test.txt

创建容器centos2中查看对应的文本内容:

[root@VM-0-10-centos volumes]# docker run -it --name centos2 --volumes-from dir centos:7
[root@a1db0373c9c8 /]# cat /dir/test.txt 
Hi I am GalenGao
it's a message from centos1

从上面的演示可以看出centos1与centos2容器对同一个目录下文件输出,均可在彼此对应的目录查看,这就达到数据共享的目的了。

删除共享数据卷

运行中的容器进行了删除,并不会影响其真实宿主机相应的内容,如果要删除容器的时候需要同时删除其数据卷,需要在最后一个挂载真实宿主机的容器中指定相应的容器数据卷,例如删除刚刚创建的容器数据卷就可以使用 docker rm -v 命令来指定同时删除关联的容器。

[root@VM-0-10-centos volumes]# docker rm -f dir -v /dir
/dir
Error response from daemon: removal of container dir is already in progress
[root@VM-0-10-centos volumes]# docker ps