Docker数据卷

Docker数据卷

1.数据卷介绍

数据卷简单的来说就是一个目录,它是由docker daemon挂载到容器中的,因此数据卷并不属于联合文件系统。也就是说数据卷是不会随着容器的丢失而丢失的。就像我们将U盘插到计算机,即使计算机的硬盘坏了,也不会影响U盘里面的数据。因此在使用docker commit提交时并不会把数据卷里面的数据提交到镜像中。

2.数据卷容器介绍

如果让两个容器共享一个数据卷,最快的办法是将数据卷挂载到两个容器上面即可。

3.挂载数据卷

docker run 或者是docker create命令时,可以指定-v参数来添加数据卷,并且这个参数可以用多次,可以挂载多个数据卷。

el:

$docker run -d -v /vol --name volume bonc:5000/busybox:v1

 

我们现在已经为容器volume挂载了一个数据卷,位置是/vol

但是这样我们不易管理,可以使用docker inspect来查看数据卷的位置:

"Mounts": [

{

"Type": "volume",

"Name": "3b1e12ca553a462526c9079e5ea95869af7b93ca98ca7f5497624c7f9ab8f00f",

"Source": "/var/lib/docker/volumes/3b1e12ca553a462526c9079e5ea95869af7b93ca98ca7f5497624c7f9ab8f00f/_data",

"Destination": "/vol",

"Driver": "local",

"Mode": "",

"RW": true,

"Propagation": ""

}

],

如果删除容器 :

$docker rm –f volume

再去查看数据卷目录会发现,数据卷还是存在的。虽然数据还是存在,但是我们的这样子做超级麻烦。

 

 

下面我们用简单的方式去解决这个问题,我们通过使用映射目录就可以方便的解决这个问题。

$ docker run -d -v /vol:/vol--name=volume bonc:5000/busybox:v1
目前数据卷存储在宿主机的/vol,不用去担心数据卷的丢失。数据卷的路径必须是绝对路径,另外删除数据卷时可以指定docker rm –v <container ID>

4.挂载数据卷容器

在上面的挂载数据卷虽然很好的解决了数据持久化的问题,但是在迁移上面还是很麻烦的。例如多个容器之间的共享数据需要迁移时,使用挂载宿主机的文件夹的方法迁移起来显得很麻烦。所以为了方便起见,我们可以启一个容器来专门负责存放数据

    $ docker run -it -v /var/lib/mysql --name=mysql_volume mysql /bin/true

上面就启动了一个数据卷容器,/bin/true是为了覆盖原有进程并防止容器退出

然后启动其他容器容器并挂载数据卷容器

    $ docker run -d --volumes-from mysql_volume --name db1 mysql

    $ docker run -d --volumes-from mysql_volume21 --name db2 mysql

甚至可以通过db1来挂载到后续启动的容器中:

    $ docker run -d --volume-from db1 --name db4 mysql

这样删除上面4个容器中的3个,数据卷也 不会丢失,即使四个都丢失了,但是还会保存在/var/lib/docker/volume/的某个目录下,这事先通过docker inspect 命令来查看volume ID.

综上所述,docker volume 并不是特别好用。 在挂载的时候一定要注意,避免以后的数据找不到。

还有补充的就是如果删除一个一个含有挂载数据卷的容器,在删除时没有用-v,则这些数据卷会成为dangling状态

    $ docker volume ls -f dangling=true #查看所有没有挂载到容器上的数据卷

删除dangling状态的数据。

    $docker volume rm <volume NAME>

>>>>>>>>>>>>小结<<<<<<<<<<<<<<<<

为了更直观的了解数据卷的挂载操作,做实验。

1.将本地宿主机不存在的文件挂载到容器中,而容器中存在,发现失败了

$ docker run --name=test -v ~/test.txt:/etc/hosts -d httpd #这里启动容器失败

报错:

/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "process_linux.go:364: container init caused "rootfs_linux.go:54: mounting \"/root/test.txt\" to rootfs \"/var/lib/docker/overlay2/549a2539ade911b73d6025bcf17bd91de98379ef21099f63edefead57863703e/merged\" at \"/var/lib/docker/overlay2/549a2539ade911b73d6025bcf17bd91de98379ef21099f63edefead57863703e/merged/etc/hosts\" caused \"not a directory\"""

: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type.

2.将本地不存在的文件夹挂载到容器的文件夹中。bonc:5000/busybox:v1镜像中存在一个/srv的文件夹,在文件夹有一个index.php文件。

    $ docker run -d --name=test14 -v ~/srv:/srv bonc:5000/busybox:v1

    最后发现容器启动成功了。

上面两个实验告诉我们,数据卷的挂载是通过把本地的目录覆盖到容器中的。也就是说宿主机文件不存在时,不能挂载;当文件夹不存在时,挂载到容器会用一个空文件夹覆盖容器原有的目录。

 

3.继续假设宿主机存在文件,容器内部存在该文件:

    $ docker run -d --name=a23 -v ~/a.txt:/srv/a.txt -d docker.io/domeos/openfalcon-domeos:0.5 #假设本地文件a.txt是存在的

4.接下来是宿主机存在文件夹,容器不存在文件夹,宿主机的a文件夹里面存在一个hello文件

    $ docker run --name=b99 -v ~/a:/srv/a -d docker.io/domeos/k8s-domeos:1.4.7 #容器启动成功

    $ docker exec -it b99 sh #进入容器

    $cd /srv/a

    $ls

    Hello

    上面这两个例子说明:

如果容器内不存在文件,宿主机可直接挂载。

5.接下来继续测试,如果容器内存在文件夹b,宿主机内存在文件夹b。这样挂载结果如下:

    $ docker run --name=y77 -v ~/b:/svr/b -d docker.io/domeos/k8s-domeos:1.4.7

会报错,容器启动失败。

6.假设宿主机是文件夹,容器也是文件夹,两个文件夹里面的内容不一样,宿主机内部是hello文件,容器文件夹里面是index.php:

$ docker run --name=c9 -v ~/a:/srv/b -d b:latest #能正确的启动

 

______________________综上所述___________________________

根据上面的6个实验,不难总结出一个规律:

宿主机文件

容器内文件

启动参数(加粗表示不存在)

容器启动情况

不存在

文件

-v ~/test.txt:/etc/hosts

启动错误

不存在

文件夹

-v ~/srv:/srv

启动正常

文件

不存在

-v ~/test.txt:/srv/test.txt

启动正常

文件夹

不存在

-v ~/test:/srv/test

启动正常

文件夹

文件

-v ~/test:/srv/test.txt

启动错误

文件夹

文件夹

-v ~/test:/srv/test

启动正常

文件

文件

-v ~/test.txt:/srv/test.txt

启动正常

文件

文件夹

-v ~/test.txt:/srv/test

启动错误

 

原文地址:https://www.cnblogs.com/cdipp/p/9642439.html