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

news2024/12/23 0:45:05

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 --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.

可以知道创建、删除等操作。主要看一下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.coloradmin.cn/o/841171.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Last-Mile Embodied Visual Navigation 论文阅读

论文阅读 题目&#xff1a;Last-Mile Embodied Visual Navigation 作者&#xff1a;JustinWasserman, Karmesh Yadav 来源&#xff1a;CoRL 时间&#xff1a;2023 代码地址&#xff1a;https://jbwasse2.github.io/portfolio/SLING Abstract 现实的长期任务&#xff08;例如…

Spring Cloud Gateway过滤器GlobalFilter详解

一、过滤器的场景 在springCloud架构中&#xff0c;网关是必不可少的组件&#xff0c;它用于服务路由的转发。对客户端进行屏蔽微服务的具体细节&#xff0c;客户端只需要和网关进行交互。所以网关顾名思义&#xff0c;就是网络的一个关卡。它就是一座城的城门守卫。所以这个守…

10亿数据、查询<10s,论基于OLAP搭建广告系统的正确姿势

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 由于流量红利逐渐消退&#xff0c;越来越多的广告企业和从业者开始探索精细化营销的新路径&#xff0c;取代以往的全流量、粗放式的广告轰炸。精细化营销意味着要在…

抓包神器-burp

Burp Suite是一款信息安全从业人员必备的集成型的渗透测试工具&#xff0c;它采用自动测试和半自动测试的方式&#xff0c;包含了 Proxy,Spider,Scanner,Intruder,Repeater,Sequencer,Decoder,Comparer等工具模块。通过拦截HTTP/HTTPS的web数据包&#xff0c;充当浏览器和相关应…

机器学习常用Python库安装

机器学习常用Python库安装 作者日期版本说明Dog Tao2022.06.16V1.0开始建立文档 文章目录 机器学习常用Python库安装Anaconda简介使用镜像源配置 Pip简介镜像源配置 CUDAPytorch安装旧版本 TensorFlowGPU支持说明 DGL简介安装DGLLife RDKitscikit-multilearn Anaconda 简介 …

RocketMQ使用

说明&#xff1a;本文介绍RocketMQ的消费模式&消息类型&#xff0c;RocketMQ的安装参考及简单使用&#xff0c;参考&#xff1a;http://t.csdn.cn/BKFPj 消费模式 RocketMQ与RabbitMQ最大的区别在于&#xff0c;RocketMQ是根据消息的Topic锁定消费者的&#xff0c;Topic属…

当不在公司时,如何在外远程登录公司内网OA系统?

在外远程登录公司内网OA系统 文章目录 在外远程登录公司内网OA系统前言1. 打开“远程桌面”选项2. 安装cpolar客户端3. 登录cpolar客户端4. 创建隧道5. 生成公网地址6. 远程连接其他电脑 前言 随着信息化办公的快速推进&#xff0c;很多企业已经用上了OA系统&#xff0c;并且我…

ubuntu上安装mosquitto服务

1、mosquitto是什么 Mosquitto 项目最初由 IBM 和 Eurotech 于 2013 年开发&#xff0c;后来于 2016 年捐赠给 Eclipse 基金会。Eclipse Mosquitto 基于 Eclipse 公共许可证(EPL/EDL license)发布&#xff0c;用户可以免费使用。作为全球使用最广的 MQTT 协议实现之一 &#x…

Diffusion扩散模型学习4——Stable Diffusion原理解析-inpaint修复图片为例

Diffusion扩散模型学习4——Stable Diffusion原理解析-inpaint修复图片为例 学习前言源码下载地址原理解析一、先验知识二、什么是inpaint三、Stable Diffusion中的inpaint1、开源的inpaint模型2、基于base模型inpaint 四、inpaint流程1、输入图片到隐空间的编码2、文本编码3、…

东芝低导通电阻N沟道MOSFET 为智能穿戴设备赋能

东芝低导通电阻N沟道MOSFET TPN6R303NC,LQ(S 为智能穿戴设备赋能 MOSFET也就是金属-氧化物半导体场效应晶体管&#xff0c;外形与普通晶体管差不多&#xff0c;但具有不同的控制特性&#xff0c;主要是通过充电和放电来切换或放大信号。 此次推出的用于智能穿戴的30V N沟道MO…

CMake的使用--以ORCA避碰C++库为例

1、安装cmake 链接&#xff1a;Download | CMake 版本需下载Binary distributions这个模块下的 Windows x64 Installer: cmake-3.27.1-windows-x86_64.msi 注意事项 1.1勾选为所有用户添加到PATH路径 Add CMake to the system PATH for all users 1.2安装路径建议直接在c…

Dueling Network

Dueling Network —— Dueling Network Architectures for Deep Reinforcement Learning 论文下载地址 论文介绍 图9. Dueling Network 模型结果示意图 Dueling Network与传统DQN的区别在于神经网络结构的不同&#xff0c;Dueling Netowrk在传统DQN的基础上只进行了微小的改动…

python 合并多个excel文件

使用 openpyxl 思路&#xff1a; 读取n个excel的文件&#xff0c;存储在一个二维数组中&#xff0c;注意需要转置。将二维数组的数据写入excel。 安装软件&#xff1a; pip install openpyxl源代码&#xff1a; import os import openpyxl # 将n个excel文件数据合并到一个…

jupyter lab环境配置

1.jupyterlab 使用虚拟环境 conda install ipykernelpython -m ipykernel install --user --name tf --display-name "tf" #例&#xff1a;环境名称tf2. jupyter lab kernel管理 show kernel list jupyter kernelspec listremove kernel jupyter kernelspec re…

微软研究院展示Project Rumi项目;参数高效微调(PEFT)

&#x1f989; AI新闻 &#x1f680; 微软研究院展示Project Rumi项目&#xff0c;通过多模态方法增强人工智能理解能力 摘要&#xff1a;微软研究院展示了Project Rumi项目&#xff0c;该项目通过结合文本、音频和视频数据&#xff0c;并采用多模态副语言提示的方法&#xf…

VL 模型 Open-Set Domain Adaptation with Visual-Language Foundation Models 论文阅读笔记

Open-Set Domain Adaptation with Visual-Language Foundation Models 论文阅读笔记 一、Abstract 写在前面 又是一周周末&#xff0c;在家的时间感觉过得很快呀。今天没得时间写博客&#xff0c;留下个标题&#xff0c;明天搞完。 论文地址&#xff1a;Open-Set Domain Adapta…

探索人工智能 | 计算机视觉 让计算机打开新灵之窗

前言 计算机视觉是一门研究如何使机器“看”的科学&#xff0c;更进一步的说&#xff0c;就是指用摄影机和电脑代替人眼对目标进行识别、跟踪和测量等机器视觉&#xff0c;并进一步做图形处理&#xff0c;使电脑处理成为更适合人眼观察或传送给仪器检测的图像。 文章目录 前言…

安全基础 --- https详解 + 数组(js)

CIA三属性&#xff1a;完整性&#xff08;Confidentiality&#xff09;、保密性&#xff08;Integrity&#xff09;、可用性&#xff08;Availability&#xff09;&#xff0c;也称信息安全三要素。 https 核心技术&#xff1a;用非对称加密传输对称加密的密钥&#xff0c;然后…

第一篇:一文看懂 Vue.js 3.0 的优化

我们的课程是要解读 Vue.js 框架的源码&#xff0c;所以在进入课程之前我们先来了解一下 Vue.js 框架演进的过程&#xff0c;也就是 Vue.js 3.0 主要做了哪些优化。 Vue.js 从 1.x 到 2.0 版本&#xff0c;最大的升级就是引入了虚拟 DOM 的概念&#xff0c;它为后续做服务端渲…

java+springboot+mysql员工工资管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的员工工资管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、员工角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;部门管理&#xff1b;员工管理&#xff1b;奖惩管理&…