K8S系列文章 之 容器存储基础 Volume

Volume

Volume是容器数据卷。我们经常创建删除一些容器,但有时候需要保留容器中的一些数据,这时候就用到了Volume。它也是容器之间数据共享的技术,可以将容器中产生的数据同步到本地。实际就是把容器中的目录挂载到运行着容器的服务器或个人电脑上。

挂载命令-v

第一种挂载volume的方式是通过命令-v来挂载。

指定路径挂载

类似于-p 主机端口:容器内端口-v也是-v 主机目录:容器内目录。这种方式是指定路径挂载。

在主机建一个/mainHome目录,我有一个centos镜像,用它跑起一个容器来,将容器的/home目录映射到主机/mainHome目录。

root@KitDevVps:~# mkdir mainHome
root@KitDevVps:~# pwd
/root
root@KitDevVps:~# docker run -it -v /root/mainHome:/home centos /bin/bash
[root@b486ed5aa77f /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@b486ed5aa77f /]# cd /home/
[root@b486ed5aa77f home]# ls
[root@b486ed5aa77f home]# touch test.txt
[root@b486ed5aa77f home]# ls
test.txt
[root@b486ed5aa77f home]# exit
exit
root@KitDevVps:~# ls /root/mainHome/
test.txt

可以看到映射之后,我进入容器内,在它的/home下创建了一个test.txt,退出容器回到主机的/root/mainHome下,发现也已经有了一个test.txt文件。

目前我们了解了修改容器内文件可以让容器外面挂载到的目录出现变化。我们尝试在容器外编辑这个test.txt文件,然后进容器内查看。虽然我们基本已经清楚这是多此一举,但还是尝试一下。

root@KitDevVps:~# cd /root/mainHome/
root@KitDevVps:~/mainHome# vim test.txt 

UTOOLS1593789920176.png

root@KitDevVps:~/mainHome# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                NAMES
b486ed5aa77f        centos              "/bin/bash"              5 minutes ago       Exited (0) 4 minutes ago                        boring_cerf
242fdc2bba7d        centos              "-it /bin/bash"          6 minutes ago       Created                                         optimistic_dubinsky
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   11 hours ago        Up 7 hours                 0.0.0.0:80->80/tcp   nginx1
7d2fd4e741ba        hello-world         "/hello"                 13 hours ago        Exited (0) 13 hours ago                         elastic_goldstine
root@KitDevVps:~/mainHome# docker start b486ed5aa77f
b486ed5aa77f
root@KitDevVps:~/mainHome# docker exec -it b486ed5aa77f /bin/bash
[root@b486ed5aa77f /]# cat /home/test.txt 
Hello Volume!

可以看到容器内的test.txt的内容也随之发生了变化。而且我们之前exit时,实际上容器就已经stop了,我们是在容器停止之后修改了本机的test.txt文件,重新运行起容器,发现容器内的test.txt文件也发生了变化。可以说是非常灵活。

注意,如果运行容器时没有使用-d,没有让其后台运行,在容器内时,可以使用ctrl+p+q来退出容器,此时容器依旧会在运行,使用exit退出,我预计它不会运行,但容器也会继续运行。这一块跟我前面结果有出入,让我摸不到头脑。后面我又有一次没有-d,exit后容器stop了,ctrl+p+q没有stop。-d后exit容器也没有stop。现在的结论就是:

  • 没有-d,使用exit,容器会stop
  • 没有-d,使用ctrl+p+q,容器不会stop
  • 没有-d,使用exit退出,容器stop,再使用docker start 容器名启动,容器依旧会在后台运行
  • 没有-d,使用ctrl+p+q退出,容器不会stop
  • 有-d,使用exit,容器不会stop
  • 有-d,使用ctrl+p+q,容器不会stop
  • 有-d,使用exit退出,容器stop,再使用docker start 容器名启动,容器依旧会在后台运行,使用ctrl+p+q
  • 有-d,使用ctrl+p+q退出,容器不会stop

可以使用docker inspect <容器id>来查看容器详细信息,其中会包括卷挂载的目录等。

如果我想用docker搞一个nginx,又不想一遍一遍地进入容器修改配置文件,因为我可能随时删除容器。此时就可以用这种方式。每次运行新容器,只需要把主机存放配置文件的目录挂载到容器存放配置文件的目录即可。因为即使删掉容器,主机的目录和里面的内容不会丢失。

注意:可以同时挂载多个目录,格式:-v 主机目录1:容器内目录1 -v 主机目录2:容器内目录2 -v...

如果只写-v 容器内目录,是匿名挂载的格式,会自动在主机生成目录。

docker volume ls是查看所有本机的卷的指令,可以用docker volume --help来查看更多用法。

root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME
local               sqlvolume

不知道为什么,竟然不显示之前我挂载的mainHome,可能是那个只是目录的映射,不是卷,用docker volume create创建出来的才是卷。

尝试一下匿名挂载和具名挂载:

具名挂载

具名挂载的命令:-v 卷名:容器内路径。卷名前面如果加上个“/”,就会变成指定路径挂载。注意区分。

具名挂载:

root@KitDevVps:~# docker run -d -P --name centos01 -v centos01:/home centos
775b213506eb2bc06228ac25d2f8e36f5abfccaba80658accc072a7fd7af6879
root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME
local               centos01
local               sqlvolume

docker run -d -P --name centos01 -v centos01:/home centos这行命令中,-d是后台运行,-P大写P是随机指定端口,-v centos01:/homecentos01是卷名,不是主机目录,这里很容易跟主机目录混淆,要留心。冒号后面是容器内目录。我在指令中加了-d让它后台运行,但docker自动把这个镜像关闭了,原因似乎是docker理解这个容器没用了,就自动关掉了。下次尝试不加-d。

删掉容器,看看volume还在不在:

root@KitDevVps:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                NAMES
775b213506eb        centos              "/bin/bash"              37 seconds ago      Exited (0) 35 seconds ago                        centos01
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   21 hours ago        Up 18 hours                 0.0.0.0:80->80/tcp   nginx1
7d2fd4e741ba        hello-world         "/hello"                 24 hours ago        Exited (0) 24 hours ago                          elastic_goldstine
root@KitDevVps:~# docker rm centos01
centos01
root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME
local               centos01
local               sqlvolume

发现删掉之后,数据卷还在,这符合我们的需求。

匿名挂载

匿名挂载:

root@KitDevVps:~# docker run -P --name centos01 -v /home centos
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   21 hours ago        Up 18 hours         0.0.0.0:80->80/tcp   nginx1
root@KitDevVps:~# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                NAMES
bca038e5ea33        centos              "/bin/bash"              45 seconds ago      Exited (0) 43 seconds ago                        centos01
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   21 hours ago        Up 18 hours                 0.0.0.0:80->80/tcp   nginx1
7d2fd4e741ba        hello-world         "/hello"                 24 hours ago        Exited (0) 24 hours ago                          elastic_goldstine
root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME
local               847c90a1bdcdcfa65d8fd316ddf53816e223b185125d519152c4a2260323b7e9
local               centos01
local               sqlvolume

可以看到匿名挂载的volume name是随机的码。但有一个其他的问题,是我明明没有加-d让它后台运行,为什么还是自动关掉了。查看日志发现日志也为空。实在不知道该如何解决自动stop容器的问题。

ro和rw

看以下命令:

docker run -it -v /root/mainHome:/home:ro centos /bin/bash
docker run -it -v /root/mainHome:/home:rw centos /bin/bash

如果在容器内路径后面加上:ro:rw,是对权限的配置,约束的是容器内的权限。ro只能从外部改变,不能从容器内部改变。默认就是rw,容器内对卷目录下的文件也可读可写。

卷的其他操作以及卷的路径

这个问题先一放,看一下docker volume命令怎么用:

root@KitDevVps:~# docker volume -h
Flag shorthand -h has been deprecated, please use --helpUsage:	docker volume COMMANDManage volumesCommands:create      Create a volumeinspect     Display detailed information on one or more volumesls          List volumesprune       Remove all unused local volumesrm          Remove one or more volumesRun 'docker volume COMMAND --help' for more information on a command.

可以知道创建、删除等操作。主要看一下inspect:

root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME
local               847c90a1bdcdcfa65d8fd316ddf53816e223b185125d519152c4a2260323b7e9
local               centos01
root@KitDevVps:~# docker volume inspect 847c90a1bdcdcfa65d8fd316ddf53816e223b185125d519152c4a2260323b7e9
[{"CreatedAt": "2020-07-04T01:53:46Z","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/847c90a1bdcdcfa65d8fd316ddf53816e223b185125d519152c4a2260323b7e9/_data","Name": "847c90a1bdcdcfa65d8fd316ddf53816e223b185125d519152c4a2260323b7e9","Options": null,"Scope": "local"}
]

现在查看的是匿名卷,可以看到路径在"Mountpoint"那一栏。docker所有的卷如果没有指定详细路径,都会放在/var/lib/docker/volumes/这个目录下,而所有的数据都在/_data下。我们看一下里面有什么:

root@KitDevVps:~# ls /var/lib/docker/volumes/847c90a1bdcdcfa65d8fd316ddf53816e223b185125d519152c4a2260323b7e9/_data/
root@KitDevVps:~# 

看来暂时还什么都没有,因为我挂载的是home目录,而且这个镜像也已经被我删了,暂时没法进它的home进行操作。我重新搞一个。为什么这次我可以运行起这个容器而不自动退出,可以看如何解决容器创建出来自动停止的问题:

root@KitDevVps:~# docker run -P -d -it --name centos01 -v centos01Volume:/home centos
e087f8443ee1f62dd68950e3f61fa039852b2dfee18a117019951b236a430548
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
e087f8443ee1        centos              "/bin/bash"              4 seconds ago       Up 2 seconds                             centos01
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   23 hours ago        Up 19 hours         0.0.0.0:80->80/tcp   nginx1
root@KitDevVps:~# docker exec -it e087f8443ee1 /bin/bash
[root@e087f8443ee1 /]# touch /home/test.txt
[root@e087f8443ee1 /]# ls /home/
test.txt
[root@e087f8443ee1 /]# exit
exit
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
e087f8443ee1        centos              "/bin/bash"              3 minutes ago       Up 3 minutes                             centos01
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   23 hours ago        Up 19 hours         0.0.0.0:80->80/tcp   nginx1
root@KitDevVps:~# ls /var/lib/docker/volumes/centos01Volume/_data/
test.txt

可以看到/var/lib/docker/volumes/centos01Volume/_data/路径下有映射的容器内/home/目录下的文件。同时注意,我在运行这个容器时使用了-d和-it,后面我exit出容器后,容器依然是在运行的。后面我自己创建的镜像run出来的容器,没有使用-d,使用exit或ctrl+p+q退出容器后,依旧也在后台运行,这让我怀疑-d除了返回id外到底有什么用。后来通过实践得知,加了-d后,run出容器来,并不直接进入容器,而是回到了本机。不加-d则会直接进入容器。

再看一下主机的/var/lib/docker下有什么:

root@KitDevVps:~# ls /var/lib/docker/
builder  buildkit  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  trust  volumes

其中containers是docker的容器,image是docker的镜像,network是docker的网络,plugins是插件,volumes就是卷。

如何解决容器创建出来自动停止的问题(重要)

我尝试运行镜像的时候与镜像交互:

docker run -d -P -it --name centos01 centos
d59e9785a1212280342817d9e5c49ca126d2eda5af8cf1ef8da194570ecf49ce
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
d59e9785a121        centos              "/bin/bash"              5 seconds ago       Up 3 seconds                             centos01
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   22 hours ago        Up 19 hours         0.0.0.0:80->80/tcp   nginx1
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
d59e9785a121        centos              "/bin/bash"              8 seconds ago       Up 7 seconds                             centos01
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   22 hours ago        Up 19 hours         0.0.0.0:80->80/tcp   nginx1

同时使用-d和-it,发现容器没有自杀,正常启动了。

尝试不使用-d,只使用-it:

root@KitDevVps:~# docker run -P -it --name centos01 centos
[root@53df37df4c1e /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

发现直接进入了镜像的命令行。输入exit退出:

[root@53df37df4c1e /]# exit
exit
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   22 hours ago        Up 19 hours         0.0.0.0:80->80/tcp   nginx1

发现镜像也自动stop了。如果运行容器时同时使用-d和-it,即使exit退出容器,容器依然会在运行。

还有的容器自动停止是其他原因,可以使用docker logs 容器id查看日志。比如sqlserver的容器,自动stop的原因可能是服务器的内存不满足它配置的需求:

root@KitDevVps:~# docker run --name mssql01 -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=******' -e 'MSSQL_PID=Express' -p 1433:1433 -v sqlvolume:/var/opt/mssql -d -it mcr.microsoft.com/mssql/server
7664784740e200dcb20d02d3f93369023f9ff3438b9aa80ccfc138df3a1f46ee
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   22 hours ago        Up 19 hours         0.0.0.0:80->80/tcp   nginx1
root@KitDevVps:~# docker ps -a
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS                            PORTS                NAMES
7664784740e2        mcr.microsoft.com/mssql/server   "/opt/mssql/bin/perm…"   8 seconds ago       Exited (1) 7 seconds ago                               mssql01
53df37df4c1e        centos                           "/bin/bash"              4 minutes ago       Exited (130) About a minute ago                        centos01
1cdd55fd90c5        nginx                            "/docker-entrypoint.…"   22 hours ago        Up 19 hours                       0.0.0.0:80->80/tcp   nginx1
7d2fd4e741ba        hello-world                      "/hello"                 25 hours ago        Exited (0) 25 hours ago                                elastic_goldstine
root@KitDevVps:~# docker logs 7664784740e2
SQL Server 2019 will run as non-root by default.
This container is running as user mssql.
To learn more visit https://go.microsoft.com/fwlink/?linkid=2099216.
sqlservr: This program requires a machine with at least 2000 megabytes of memory.
/opt/mssql/bin/sqlservr: This program requires a machine with at least 2000 megabytes of memory.

日志中写了它至少需要2000M内存,我的服务器就是2000M内存,看来还不够。可能要4000M内存的服务器才能玩它。

Dockerfile挂载卷的方式

可以使用DockerFile来挂载卷。DockerFile也是重要的Docker知识点,我一直没搞懂,下次尝试搞懂它,这次先用它挂载卷。

Dockerfile看起来就像是构建docker镜像的配置文件,利用它可以生成镜像。试一下。

先开一个目录用来写Dockerfile和存放生成的镜像:

root@KitDevVps:~# cd /home/
root@KitDevVps:/home# mkdir dockerfile-volume-test
root@KitDevVps:/home# ls
dockerfile-volume-test
root@KitDevVps:/home# cd dockerfile-volume-test/
root@KitDevVps:/home/dockerfile-volume-test# 

这个目录是/home/dockerfile-volume-test。在里面写一个dockerfile1,然后在里面写一些脚本。通过这些脚本可以生成一个docker镜像。脚本是一个个的命令,每个命令都是一层

# 以centos镜像为基础
FROM centos # 挂载卷,在镜像生成的时候就把卷挂载出来,可以挂载多个目录,目录都会在容器中生成,在本机上是以匿名挂载的方式在默认的位置。当然要run出容器来才会挂载,只build镜像当然不会挂载
VOLUME ["volume1","volume2"]# 写一个命令行,输出一条语句,证明脚本运行到了这里,镜像构建成功
CMD echo "build succeed"# 构建完之后,我们进入容器时希望走bash
CMD /bin/bash

dockerfile写好了,使用docker build命令构建镜像:

root@KitDevVps:/home/dockerfile-volume-test# docker build -f dockerfile1 -t kit/centos .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos---> 831691599b88
Step 2/4 : VOLUME ["volume1","volume2"]---> Running in f634ab6900f1
Removing intermediate container f634ab6900f1---> 10d1359b311e
Step 3/4 : CMD echo "build succeed"---> Running in e505fce33f96
Removing intermediate container e505fce33f96---> bad661d7a8e7
Step 4/4 : CMD /bin/bash---> Running in 59efa3a8897d
Removing intermediate container 59efa3a8897d---> 9347f3c0dcd9
Successfully built 9347f3c0dcd9
Successfully tagged kit/centos:latest

看一下第一行的命令:

-f 后加dockerfile的地址。

-t就是target,就是生成的镜像的名字。注意开头不要有/,会被识别成目录。最后可以用冒号":"来指定tag,可以写成1.0,1.1等,不写的话默认就是latest。

最后的“.”是指生成在当前目录下,也可以换成指定的目录。

再看一下build的过程,第一步是拿到基础镜像,第二步是挂载,第三步写出了我们刚才写的CMD命令,第四步进入了/bin/bash。

我再尝试构建一个镜像,跟这个名字相同,tag为1.0,并且最后用绝对路径指定镜像生成的路径:

root@KitDevVps:/home/dockerfile-volume-test# docker build -f dockerfile1 -t kit/centos:1.0 /home/dockerfile-volume-test/
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos---> 831691599b88
Step 2/4 : VOLUME ["volume1","volume2"]---> Using cache---> 10d1359b311e
Step 3/4 : CMD echo "build succeed"---> Using cache---> bad661d7a8e7
Step 4/4 : CMD /bin/bash---> Using cache---> 9347f3c0dcd9
Successfully built 9347f3c0dcd9
Successfully tagged kit/centos:1.0
root@KitDevVps:/home/dockerfile-volume-test# docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
kit/centos                       1.0                 9347f3c0dcd9        4 minutes ago       215MB
kit/centos                       latest              9347f3c0dcd9        4 minutes ago       215MB
centos                           latest              831691599b88        2 weeks ago         215MB
mcr.microsoft.com/mssql/server   latest              d2520a2df464        2 weeks ago         1.51GB
nginx                            latest              2622e6cca7eb        3 weeks ago         132MB
hello-world                      latest              bf756fb1ae65        6 months ago        13.3kB

可以看到两个镜像名字相同,只有版本号不同,连id也相同。用id删除镜像的话估计就全都删除了,我尝试能不能用名字加tag只删除其中一个。先删latest:

root@KitDevVps:/home/dockerfile-volume-test# docker rmi kit/centos:latest
Untagged: kit/centos:latest
root@KitDevVps:/home/dockerfile-volume-test# docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
kit/centos                       1.0                 9347f3c0dcd9        2 minutes ago       215MB
centos                           latest              831691599b88        2 weeks ago         215MB
mcr.microsoft.com/mssql/server   latest              d2520a2df464        2 weeks ago         1.51GB
nginx                            latest              2622e6cca7eb        3 weeks ago         132MB
hello-world                      latest              bf756fb1ae65        6 months ago        13.3kB

我试验了两次,rmi后的容器名称加上":latest"和不加,均能删掉latest,但不删掉1.0。看来对于id相同的容器,可以使用rmi 容器名加tag的方式来删除。

root@KitDevVps:/home/dockerfile-volume-test# docker rmi kit/centos:1.0
Untagged: kit/centos:1.0
Deleted: sha256:9347f3c0dcd9dd7a6650e73a329ac77582565f5e640cb2b10c89bb90173dde4e
Deleted: sha256:bad661d7a8e75bf3fad12348712826a57571e53d95c77acc4c1b6aa80032a3e6
Deleted: sha256:10d1359b311e2fe98e728368d44778aae5083f9e836f883a7c423b03fa0ad93b
root@KitDevVps:/home/dockerfile-volume-test# docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
centos                           latest              831691599b88        2 weeks ago         215MB
mcr.microsoft.com/mssql/server   latest              d2520a2df464        2 weeks ago         1.51GB
nginx                            latest              2622e6cca7eb        3 weeks ago         132MB
hello-world                      latest              bf756fb1ae65        6 months ago        13.3kB

删掉了。我重新构建出1.0来,尝试run起来一个容器并且进入。

root@KitDevVps:/home/dockerfile-volume-test# docker run -it kit/centos:1.0 /bin/bash
[root@6becde880c2b /]# 
[root@6becde880c2b /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume1  volume2

可以看到不但成功进入了我们的容器,ls了一下发现容器内根目录有volume1 volume2两个目录,我们在run出这个容器的时候名没有添加-v,也就是说这两个目录是我们通过在dockerfile中写命令,生成容器时来自动挂载的。

实际上不输入/bin/bash也可以进入容器,我猜测是前面dockerfile的CMD /bin/bash起了作用。

我们进入volume1,创建一个文件test.txt,然后另开一个终端看一下主机中有没有以匿名挂载的方式挂载到默认路径,顺便看看其中有没有test.txt:

[root@6becde880c2b /]# touch volume1/test.txt
[root@6becde880c2b /]# ls volume1
test.txt

另外开一个终端:

root@KitDevVps:~# ls /var/lib/docker/volumes/
8f76e936d3b3b0f119ca3424578a0dc2f23b19060017fdc2b84d4e2eede1f1e4  acd4c09b3f77f070e9a900cc33e3326f30122ce97383ed188335d805ade381b6  metadata.db
root@KitDevVps:~# ls /var/lib/docker/volumes/8f76e936d3b3b0f119ca3424578a0dc2f23b19060017fdc2b84d4e2eede1f1e4/_data/
root@KitDevVps:~# ls /var/lib/docker/volumes/acd4c09b3f77f070e9a900cc33e3326f30122ce97383ed188335d805ade381b6/_data/
test.txt

可以看到默认路径下有两个匿名的挂载目录,其中acd开头的目录下的_data中存在一个我们创建的test.txt,显然它就是容器内的volume1。

除了记住这个默认路径,还可以通过docker imspect 容器id的方式查看容器的详细信息来找到挂载路径:

root@KitDevVps:~# docker inspect 6becde880c2b..."Mounts": [{"Type": "volume","Name": "8f76e936d3b3b0f119ca3424578a0dc2f23b19060017fdc2b84d4e2eede1f1e4","Source": "/var/lib/docker/volumes/8f76e936d3b3b0f119ca3424578a0dc2f23b19060017fdc2b84d4e2eede1f1e4/_data","Destination": "volume2","Driver": "local","Mode": "","RW": true,"Propagation": ""},{"Type": "volume","Name": "acd4c09b3f77f070e9a900cc33e3326f30122ce97383ed188335d805ade381b6","Source": "/var/lib/docker/volumes/acd4c09b3f77f070e9a900cc33e3326f30122ce97383ed188335d805ade381b6/_data","Destination": "volume1","Driver": "local","Mode": "","RW": true,"Propagation": ""}],...

我们构建镜像常常是自己使用或者公司内部使用,可能常常需要用这种方式自动挂载,而不使用-v。

数据卷容器(容器之间数据卷共享)

还可以通过容器之间数据卷共享的方式在多个容器之间共享数据,比如有多个mssql,就能共享数据库中的数据。

首先需要一个父容器,还需要一个子容器去挂载它,实现数据同步。使用--volumes-from命令。

先删除主机上所有的卷:

root@KitDevVps:~# docker volume rm $(docker volume ls -q)
8f76e936d3b3b0f119ca3424578a0dc2f23b19060017fdc2b84d4e2eede1f1e4
0692a62975fed8394be202bac773ff8fe9a53f4a406d34b8eb8f8fba2827d393
acd4c09b3f77f070e9a900cc33e3326f30122ce97383ed188335d805ade381b6
bfe36976df800a733703b69fcf6b7bea95e68fc554588756c241705ea83a29a2
root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME

尝试创建三个容器,实现数据共享,使用我们自己build的镜像来做。先运行起一个容器,取名docker01,作为父容器,顺便进入容器内部:

root@KitDevVps:~# docker run -it --name docker01 kit/centos:1.0
[root@dcd5c3b67f9b /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume1  volume2

发现依旧生成了volume1 volume2。使用ctrl+p+q或exit退出容器(但后面我创建docker02时使用exec退出它,容器就自动停止运行了。),然后再创建它的子容器docker02,在run命令中加上--volumes-from docker01,仿佛是继承了docker01的volumes:

root@KitDevVps:~# docker run -it --name docker02 --volumes-from docker01 kit/centos:1.0
[root@0b900529dd5b /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume1  volume2

发现02中依旧有volume1 volume2。可以使用ctrl+p+q退出容器,容器依旧还在后台运行。此时查看主机的数据卷,发现还是只有docker01的那两个数据卷:

root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME
local               62208e194cb6d971e0e1610f603ac8ae90a2df8d3b5b8c198fd1523a62baf537
local               d7fc935ed1bf694e9efbf88cf20722d704201a1fd86d87ea0a6e17840301f830

为了验证两个容器数据是否互通,另开一个终端,使用docker attach进入01,修改volume1,然后进入02查看是否变化。使用docker attachdocker exec似乎更简单:

root@KitDevVps:~# docker attach docker01
[root@dcd5c3b67f9b /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume1  volume2
[root@dcd5c3b67f9b /]# touch volume1/test.txt
[root@dcd5c3b67f9b /]# ls volume1
test.txt

再看docker02:

root@KitDevVps:~# docker attach docker02
[root@0b900529dd5b /]# ls volume1
test.txt

果然也存在了这个文件。再在02中touch一个,看看01有没有改变:

[root@0b900529dd5b /]# touch volume1/test2.txt
[root@0b900529dd5b /]# ls volume1
test.txt  test2.txt

去01中看:

[root@dcd5c3b67f9b /]# ls volume1
test.txt  test2.txt

果然也存在了。

下面再尝试以下创建docker03 --volumes-from 01,再创建docker04 --volumes-from 02,看看可不可以:

root@KitDevVps:~# docker run -d -it --name docker03 --volumes-from docker01 kit/centos:1.0
51ce86e015fd6b86651f28ecf66e924082fd86fd67ac15af5968ebe3706a09f4
root@KitDevVps:~# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
51ce86e015fd        kit/centos:1.0      "/bin/sh -c /bin/bash"   9 seconds ago       Up 8 seconds                             docker03
0b900529dd5b        kit/centos:1.0      "/bin/sh -c /bin/bash"   15 minutes ago      Up 15 minutes                            docker02
dcd5c3b67f9b        kit/centos:1.0      "/bin/sh -c /bin/bash"   26 minutes ago      Up 26 minutes                            docker01
1cdd55fd90c5        nginx               "/docker-entrypoint.…"   31 hours ago        Up 27 hours         0.0.0.0:80->80/tcp   nginx1
root@KitDevVps:~# docker attach docker03
[root@51ce86e015fd /]# ls volume1 
test.txt  test2.txt

03是挂载了01,数据同步了。再创建04挂载02试试:

root@KitDevVps:~# docker run -d -it --name docker04 --volumes-from docker02 kit/centos:1.0
018a33472a829fcc93c54a5259397800459c78d6af87db24a208a333cd5bc0b2
root@KitDevVps:~# docker attach docker04
[root@018a33472a82 /]# ls volume1
test.txt  test2.txt

也是可以的。此时查看主机数据卷:

root@KitDevVps:~# docker volume ls
DRIVER              VOLUME NAME
local               62208e194cb6d971e0e1610f603ac8ae90a2df8d3b5b8c198fd1523a62baf537
local               d7fc935ed1bf694e9efbf88cf20722d704201a1fd86d87ea0a6e17840301f830

还是那两个。即使把docker01删掉,其它容器的数据也不会丢失,删别的也一样。只要有容器还在用这些数据,就不会丢失。同时,因为我们使用-v或者dockerfile等方式持久化到了本地,所以就算容器全删掉,主机上的卷也不会丢失,卷内创建的文件也还在,这是我实验过的。如果2断了,1和3依旧是挂载着的,可以看出似乎不是链式的。

UTOOLS1593864036286.png

上图是狂神的教程里的图,指容器卷共享是互相拷贝的概念,而不是共用同一块存储的概念。

在实际项目中可以用于多个redis或者mssql等实现数据共享。也可以做集群的时候进行配置文件共享。

有没有-d与exit和ctrl+p+q两种退出方式之间的关系(难点)

有-d指的是run出容器的时候添加了-d这个option。

  • 没有-d,使用exit,容器会stop
  • 没有-d,使用ctrl+p+q,容器不会stop
  • 没有-d,使用exit退出,容器stop,再使用docker start 容器名启动,容器依旧会在后台运行
  • 没有-d,使用ctrl+p+q退出,容器不会stop
  • 有-d,使用exit,容器不会stop
  • 有-d,使用ctrl+p+q,容器不会stop
  • 有-d,使用exit退出,容器stop,再使用docker start 容器名启动,容器依旧会在后台运行
  • 有-d,使用ctrl+p+q退出,容器不会stop

以上结论并不全对,因为我后来run一个ubuntu的时候,出现了上面之外的情况,总之我选择以后只使用ctrl+p+q来退出容器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/55265.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git报错:Error merging: refusing to merge unrelated histories

碰对了情人&#xff0c;相思一辈子。 打命令&#xff1a;git pull origin master --allow-unrelated-histories 然后等一会 再push 切记不要有冲突的代码 需要改掉~

零代码爬虫平台SpiderFlow的安装

什么是 Spider Flow &#xff1f; Spider Flow 是一个高度灵活可配置的爬虫平台&#xff0c;用户无需编写代码&#xff0c;以流程图的方式&#xff0c;即可实现爬虫。该工具支持多数据源、自动保存至数据库、任务监控、抓取 JS 动态渲染页面、插件扩展&#xff08;OCR 识别、邮…

【IMX6ULL驱动开发学习】22.IMX6ULL开发板读取ADC(以MQ-135为例)

IMX6ULL一共有两个ADC&#xff0c;每个ADC都有八个通道&#xff0c;但他们共用一个ADC控制器 1.设备树 在imx6ull.dtsi文件中已经帮我们定义好了adc1的节点部分信息 adc1: adc02198000 {compatible "fsl,imx6ul-adc", "fsl,vf610-adc";reg <0x0219…

【性能测试】关于系统用户数,并发用户数,在线用户数,吞吐量

目录 1、概念 系统用户数 在线用户数 并发用户数 计算公式 2、吞吐量 资料获取方法 1、概念 系统用户数 狭义上来说&#xff0c;可以理解为系统注册用户数&#xff1b;广义上来说&#xff0c;可以理解为所有访问过系统的用户数 在线用户数 狭义上来说&#xff0c;可以…

无涯教程-Lua - Arrays(数组)

数组是对象的有序排列&#xff0c;可以是包含行集合的一维数组&#xff0c;也可以是包含多行和多列的多维数组。 在Lua中&#xff0c;数组是使用带有整数的索引表实现的。数组的大小不是固定的&#xff0c;并且可以根据无涯教程的要求(取决于内存限制)来增长。 一维数组 一维…

6.6.tensorRT高级(1)-mmdetection框架下yolox模型导出并推理

目录 前言1. yolox导出2. yolox推理3. 补充知识3.1 知识点3.2 mmdetection 总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习…

vue 前端页面开发经验记录

本博文记录了在vue项目开发中的一些经验&#xff0c;具体包含&#xff1a;class动态绑定、子页面刷新、注入函数到子页面、数据加载效果、单击后编辑、文件上传、数据分页、表单提交等的使用记录。 1、class动态绑定 根据变量的值绑定不同的class样式&#xff0c;这里ftype的…

ORACLE和MYSQL区别

1&#xff0c;Oracle没有offet,limit&#xff0c;在mysql中我们用它们来控制显示的行数&#xff0c;最多的是分页了。oracle要分页的话&#xff0c;要换成rownum。 2&#xff0c;oracle建表时&#xff0c;没有auto_increment&#xff0c;所有要想让表的一个字段自增&#xff0c…

Webpack怎么使用?

Webpack 使用 前几篇文章中已经介绍了如何初始化包管理器 package.json 这里不再重复介绍&#xff0c;如有需要请查看 搭建工程化项目。 安装 :::warning 注意 请确保你已经安装了 yarn&#xff0c;如有需要请查看 搭建工程化开发环境。 ::: 通过命令 yarn add webpack web…

Grafana集成prometheus(4.Grafana添加预警)

上文已经完成了grafana对prometheus的集成及数据导入&#xff0c;本文主要记录grafana的预警功能&#xff08;以内存为例&#xff09; 添加预警 添加入口&#xff08;2个&#xff09; databorard面板点击edit&#xff0c;下方有个Alert的tab&#xff0c;创建Alert rules依赖…

LabVIEW使用DSA技术从X射线图像测量肺气容量

LabVIEW使用DSA技术从X射线图像测量肺气容量 相衬X射线&#xff08;PCX&#xff09;成像技术利用相邻介质之间折射率的微小差异来增强传统X射线成像通常不可见的物体的边界。事实证明&#xff0c;这一进展在一系列生物医学和材料科学中非常有益于材料表征、疾病检测以及解剖形…

SpringBoot项目增加logback日志文件

一、简介 在开发和调试过程中&#xff0c;日志是一项非常重要的工具。它不仅可以帮助我们快速定位和解决问题&#xff0c;还可以记录和监控系统的运行状态。Spring Boot默认提供了一套简单易用且功能强大的日志框架logback&#xff0c;本文将介绍如何在Spring Boot项目中配置和…