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
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:/home
的centos01
是卷名,不是主机目录,这里很容易跟主机目录混淆,要留心。冒号后面是容器内目录。我在指令中加了-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 attach
比docker 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依旧是挂载着的,可以看出似乎不是链式的。
上图是狂神的教程里的图,指容器卷共享是互相拷贝的概念,而不是共用同一块存储的概念。
在实际项目中可以用于多个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来退出容器。
相关文章:

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

【CHI】架构介绍
Learn the architecture - Introducing AMBA CHI AMBA CHI协议导论--言身寸 1. AMBA CHI简介 一致性集线器接口(CHI)是AXI一致性扩展(ACE)协议的演进。它是Arm提供的高级微控制器总线架构(AMBA)的一部分。…...

hcip的ospf综合实验
题目 拓扑图 IP地址分配及环回 R1 < Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]sysname r1 [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 172.16.0.1 27 Aug 6 2023 19:03:33-08:00 r1 %%01IFNET/4/LINK_STATE(l)[0]:The line protocol I…...

AP5179 高端电流采样降压恒流驱动IC SOP8 LED车灯电源驱动
产品描述 AP5179是一款连续电感电流导通模式的降压恒流源,用于驱动一颗或多颗串联LED输入电压范围从 5 V 到 60V,输出电流 最大可达 2.0A 。根据不同的输入电压和外部器件, 可以驱动高达数十瓦的 LED。内置功率开关,采用高端电流…...

vue3+vite项目配置ESlint、pritter插件
配置ESlint、pritter插件 在 Vue 3 Vite 项目中,你可以通过以下步骤配置 ESLint 和 Prettier 插件: 安装插件: 在项目根目录下,打开终端并执行以下命令安装 ESLint 和 Prettier 插件: npm install eslint prettier e…...

K8S kubeadm搭建
kubeadm搭建整体步骤 1)所有节点进行初始化,安装docker引擎和kubeadm kubelet kubectl 2)生成集群初始化配置文件并进行修改 3)使用kubeadm init根据初始化配置文件生成K8S的master控制管理节点 4)安装CNI网络插件&am…...

Squeeze-and-Excitation Networks阅读笔记一
文章目录 Abstract1 INTRODUCTION Abstract 卷积算子(convolution operator)是卷积神经网络(cnn)的核心组成部分,它使网络能够通过融合每层局部接受域内的空间和通道信息来构建信息特征。广泛的先前研究已经调查了这种…...

LabVIEW开发3D颈动脉图像边缘检测
LabVIEW开发3D颈动脉图像边缘检测 近年来,超声图像在医学领域对疾病诊断具有重要意义。边缘检测是图像处理技术的重要组成部分。边缘包含图像信息。边缘检测的主要目的是根据强度和纹理等属性识别图像中均匀区域的边界。超声(US)图像存在视觉…...

python10.4.3
10.4.3重构 错误实例 import jsondef laoyonghu(): #获取老用户名字filenameusername.jsonwith open(filename) as f:usernamejson.load(f)return usernamedef xinyonghu(): #获取新用户名字filenameusername.jsonusernameinput("whats your name:")with ope…...

系统架构设计高级技能 · 软件架构概念、架构风格、ABSD、架构复用、DSSA(一)【系统架构设计师】
系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA(一)【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估(二)【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…...

Vue中,$forceUpdate()的使用
在Vue官方文档中指出,$forceUpdate具有强制刷新的作用。 那在vue框架中,如果data中有一个变量:age,修改他,页面会自动更新。 但如果data中的变量为数组或对象,我们直接去给某个对象或数组添加属性,页面是识…...

K8s中的Ingress
1.把端口号对外暴露,通过ip端口号进行访问 使用Service里面的NodePort实现 2.NodePort缺陷 在每个节点上都会起到端口,在访问时候通过任何节点,通过节点ip暴露端口号实现访问 意味着每个端口只能使用一次,一个端口对应一个应用…...

c++调用ffmpeg api录屏 并进行udp组播推流
代码及工程见https://download.csdn.net/download/daqinzl/88155241 开发工具:visual studio 2019 播放,采用ffmpeg工具集里的ffplay.exe, 执行命令 ffplay udp://224.1.1.1:5001 主要代码如下: #include "pch.h" #include <iostream>…...

war包方式安装linux和windows的geoserver
注意: 从Java 9开始,Oracle已经不再单独提供JRE(Java Runtime Environment)了,而是直接将JRE集成在JDK(Java Development Kit)中。这是因为JRE包含了运行Java程序所需的环境,而JDK除…...

安装CUDA与CUDNN与Pytorch(最新超级详细图文版本2023年8月最新)
一、安装CUDA 1.1、下载安装包 cuda可以认为就是Nvidia为了显卡炼丹搞的一个软件,其下载地址为:CUDA Toolkit 12.2 Update 1 Downloads | NVIDIA Developer 当你点进这个链接的时候,你需要依次选择 1是选择系统,这里选windows…...

内存快照:宕机后,Redis如何实现快速恢复?RDB
AOF的回顾 回顾Redis 的AOF的持久化机制。 Redis 避免数据丢失的 AOF 方法。这个方法的好处,是每次执行只需要记录操作命令,需要持久化的数据量不大。一般而言,只要你采用的不是 always 的持久化策略,就不会对性能造成太大影响。 …...

Linux之 Ubuntu 安装常见服务 (二) Tomcat
安装TomCat 服务 1、安装JDK环境 https://www.oracle.com/java/technologies/downloads/ 下载的官网 wget https://download.oracle.com/java/20/latest/jdk-20_linux-x64_bin.deb (sha256) 使用dpkg进行软件安装时,提示:dpkg:处理软件包XX…...

docker 配置 Mysql主从集群
Docker version 20.10.17, build 100c701 MySQL Image version: 8.0.32 Docker container mysql-master is source. mys ql-replica is replication. master source. replica slave.名称叫法不一样而已。 Choose one of the way,与replica同步数据两种情况&…...

Layui实现OA会议系统之会议管理模块总合
目录 一、项目背景 二、项目概述 1. 概述 2. 环境搭建 3. 工具类引用 4. 功能设计 4.1 会议发布 4.2 我的会议 4.3 会议审批 4.4 会议通知 4.5 待开会议 4.6 历史会议 4.7 所有会议 5. 性能优点 5.1 兼容性好 5.2 可维护性和可扩展性 5.3 轻量灵活 5.4 模块化设计…...

fishing之踩坑篇捕获数据不齐全
文章目录 一、问题记录二、解决方法三、更新钓鱼模板四、进行点击邮件五、查看仪表盘免责声明 一、问题记录 通过点击邮件内的链接,提交数据,但是只记录密码,无法记录username 二、解决方法 对于需要被捕获的表单数据,除了inp…...

ppt使用笔记
文章目录 如何让文档好看纯文字绝对不可行多用流程图和效果图切换动画母版音乐视频 作品渐变星空放大镜随机抽奖 其他快捷键 作为一个开发,对这种表现类型的软件一直不太上心,但有些场景要用到ppt,例如述职和项目案例分享。 很直观的体验就是…...

java中的hashmap和concurrenthashmap解析
hashmap的初始化数组大小为16,如果发生哈希冲突的时候在当前的索引后面采用头插法以链表的形式继续插入节点。 concurrenthashmap的结构图如下所示: 本身不是16个节点吗?这里分为两个长度为4的数组,变成了4*4总共16个节点&#x…...

元素2D转3D 椭圆形旋转实现
椭圆旋转功能展示 transform-style: preserve-3d;(主要css代码) gif示例(背景图可插入透明以此实现边框线的旋转) 导致的无法点击遮挡问题可以参考我的另一个文章 穿透属性-----------------------css穿透属性 实时代码展示...

Centos7.9 制作openssh9.2p2 rpm升级包和升级实战
一、背景说明 Centos7.9 默认安装的openssh 版本为7.4p1,经绿盟扫描,存在高危漏洞,需要升级到最新。 官网只提供编译安装包,为了方便升级,先通过编译安装包,制作rpm包,并进行升级 如下为做好…...

JavaScript学习(3)
Web API 是开发人员的梦想。 它可以扩展浏览器的功能它可以极大简化复杂的功能它可以为复杂的代码提供简单的语法 什么是 Web API? API 指的是应用程序编程接口(Application Programming Interface)。 Web API 是 Web 的应用程序编程接口…...

2023华为OD机试真题Java实现【寻找最大价值的矿堆/深度优先搜索】
前言 本题使用Java实现,如果需要Python代码,请点击以下链接 点我 题目 我们规定,0表示空地,1表示银矿、2表示金矿,矿堆表示由相邻的金矿或银矿连接形成的地图。 银矿价值是1 ,金矿价值是2 ,你的目标是找出地图中最大价值的矿堆,并且输出该矿堆的价值 示例1 输入:…...

MyCat概述
1.MyCat概述 MyCat是阿里巴巴的产品,他是开源的、基于Java语言编写的MySQL数据库中间件。可以像使用mysql一样来使用mycat,对于开发人员来说根本感觉不到mycat的存在。 MyCat下载地址:http://dl.mycat.org.cn/ MyCat官网:http:/…...

【LeetCode】【数据结构】单链表OJ常见题型(一)
👀樊梓慕:个人主页 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》 🌝每一个不曾起舞的日子,都是对生命的辜负。 目录 前言: 【LeetCode】203.移除链表元素 【LeetCo…...

QGraphicsView实现简易地图3『局部加载-地图缩放』
前文链接:QGraphicsView实现简易地图2『瓦片经纬度』 第一篇文章提到过,当地图层级较大时,暴力全加载地图会造成程序卡顿,因此需要实现地图的局部加载。 实现思路:以地图窗口(以下称为视口)为地…...

bash的特性(二)IO重定向与管道
bash的I/O重定向及管道 一、概述 在shell中,最常使用的fd(file descriptor)有三个,标准输入,标准输出,错误输出。进程用文件描述符来管理打开的文件。 名称 文件描述符 标准输入(stdin) 0 键盘,也可以…...