数据卷
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS,可以提供很多有用的特定:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 数据卷的更新,不会影响镜像
- 数据卷默认会一直存在,即使容器被删除
- 用容器操作数据卷,用数据卷操作容器,都是会产生相同的效果
注意
数据卷的使用,类似于Linux下对目录或文件进行mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看到的挂载的数据卷。
数据卷操作
Docker volume(数据卷)是Docker中用于在容器和主机之间共享和持久化数据的机制。它使得容器之间的数据共享和容器的数据持久化成为可能。
Docker volume的主要特点包括:
- 数据持久性:即使容器被删除,Volume中的数据也不会丢失,因为它们存储在宿主机上。
- 数据共享:多个容器可以共享同一个Volume,使得数据共享变得简单方便。
- 类型多样:Docker支持多种类型的Volume,包括本地Volume、远程Volume以及插件支持的Volume等。
以下是一个Docker volume的示例,演示如何创建、使用和管理Volume:
示例
- 创建Docker Volume
使用docker volume create
命令可以创建一个新的Volume:
docker volume create my-volume
这条命令会创建一个名为my-volume
的新Volume。
- 查看Docker Volume
使用docker volume ls
命令可以查看当前系统中存在的所有Docker Volume:
docker volume ls
输出中会列出所有Volume的详细信息,包括它们的名称和驱动程序。
- 将Volume挂载到容器
当创建容器时,可以使用-v
或--volume
参数将Volume挂载到容器中的指定路径。例如:
docker run -d -v my-volume:/data my-image
这条命令会启动一个容器,并将my-volume
挂载到容器内的/data
目录。容器内的/data
目录现在将共享my-volume
中的数据。
- 查看Volume的挂载位置
有时,你可能想要知道Volume在宿主机上的具体挂载位置。可以通过docker volume inspect
命令获取:
docker volume inspect my-volume
输出中会包含Volume的详细信息,包括其挂载点(Mountpoint),这就是Volume在宿主机上的实际位置。
- 删除Docker Volume
当不再需要某个Volume时,可以使用docker volume rm
命令删除它:
docker volume rm my-volume
这条命令会删除my-volume
以及其中的所有数据。请注意,如果Volume正被容器使用,则无法直接删除,需要先停止并移除相关的容器。
[root@server ~]# docker volume create my-volume #在Linux主机中创建一个名为my-volume的数据卷
my-volume
[root@server ~]# docker volume ls #查看主机中的数据卷
DRIVER VOLUME NAME
local 2656990227a34c0f5e8022aa8a05a7be0c91554a28b2d71e8f4a51d73a5e36f4
local my-volume
[root@server ~]# docker volume inspect my-volume #查看my-volume数据卷的信息
[
{
"CreatedAt": "2024-03-25T11:32:05+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
"Name": "my-volume",
"Options": null,
"Scope": "local"
}
]
[root@server _data]# docker run -d -P --name web1 -v my-volume:/data nginx:latest
34ceb2d4ea950e140ef7786863ac9fe0a79c295d4a183cb4628db4c62ff699b5
[root@server _data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
34ceb2d4ea95 nginx:latest "/docker-entrypoint.…" 21 seconds ago Up 20 seconds 0.0.0.0:32769->80/tcp, :::32769->80/tcp web1
[root@server _data]# docker exec -it web1 bash #进入容器中
root@34ceb2d4ea95:/# ls / #发现出现了/data目录
bin dev etc lib64 opt run sys var
boot docker-entrypoint.d home media proc sbin tmp
data docker-entrypoint.sh lib mnt root srv usr
root@34ceb2d4ea95:/# cd /data
root@34ceb2d4ea95:/data# ls
root@34ceb2d4ea95:/data# touch file.txt #创建一个file.txt文件
root@34ceb2d4ea95:/data# ls
file.txt
root@34ceb2d4ea95:/data# cd
root@34ceb2d4ea95:~# exit #退出容器
exit
[root@server _data]# cd /var/lib/docker/volumes/my-volume/_data/ #切换到数据卷中
[root@server _data]# ls #发现了我们在容器中创建的file.txt
file.txt
[root@server _data]#
[root@server _data]# docker inspect web1 #显示结果如下图
[root@server _data]# 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 unused local volumes
rm Remove one or more volumes
[root@server _data]# docker volume rm my-volume #数据卷正在使用,所以不能删除数据卷,需要关闭或删除容器后,再删除数据卷
Error response from daemon: remove my-volume: volume is in use - [34ceb2d4ea950e140ef7786863ac9fe0a79c295d4a183cb4628db4c62ff699b5]
- 数据卷是被设计用来持久化数据的,它的生命周期独立于容器, Docker不会在容器被删除后自动删除数据卷, 并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用
docker rm -v
这个命令。 - 无主的数据卷可能会占据很多空间,要清理请使用以下命令:
[root@server _data]# docker volume prune
查看镜像,容器,数据卷所占空间
[root@server _data]# docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 3 1 891.8MB 705.1MB (79%)
Containers 1 1 1.095kB 0B (0%)
Local Volumes 2 1 0B 0B
Build Cache 0 0 0B 0B
Docker的网络模式
当你安装docker
时,它会自动创建三个网络
[root@server ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
69cf9fe45652 bridge bridge local
211a8fdf9c39 host host local
fa566b41018a none null local
- bridge:此模式会为每一个容器分配,设置IP地址等,使用
--net或--network=bridge
指定,默认网络模式
- host:使用
宿主机的IP和端口
,使用--net或--network=host
指定 - none:该模式
关闭
了容器的网络功能
,使用--net或--network=none
指定,使容器不能通信
,只能和自己玩
- container:和一个指定的容器共享IP,端口,使用
--net或--network=container:指定容器名
指定
查看指定容器的网络模式
[root@server ~]# docker inspect linux-ubuntu | grep -i network
"NetworkMode": "bridge",
"NetworkSettings": {
"Networks": {
"NetworkID": "69cf9fe45652f27db873a0f1dbcc7f36b7357af33884f51356c4c38f41ca5181",
bridge
模式
-
Docker
的Bridge
网络模式是Docker
的默认网络模式
。当不指定网络类型
时,所创建的容器默认
会采用这种网络模式
。Bridge网络
模式为每一个容器分配一个Network Namespace、IP
等,并将容器的网络连接到一个网桥
(默认为docker0
)上。 -
在
Bridge网络模式
下,同一个宿主机上
所有容器
默认会在同一个网段
(默认网段为172.17.0.0/16
)下,并且相互之间可以通信以及访问外部网络(前提是宿主机可以访问外部网络)。这种网络模式提供了容器之间的自动DNS解析,使得容器化应用程序可以轻松地相互通信,同时提高了安全性。 -
Bridge网络模式
是基于Linux bridge
的虚拟网络实现
。Docker引擎
在创建一个Bridge网络
时,会创建一个新的虚拟网桥
(命名为docker0
),然后将主机上
的所有Docker容器
的虚拟网卡接口
连接到这个虚拟网桥
上。每个容器
的虚拟网卡接口
都包含一个MAC地址
和一个唯一的IP地址
,这些信息用于标识和路由容器之间的数据包。 -
此外,
Docker
的Bridge网络
驱动会自动在宿主机上安装好防火墙规则
,隔离
开不同网桥
之间的直接通信
,以确保安全性
。Bridge网络适用于同一个Docker daemon宿主机下的容器。对于不同主机之间的通信,可以在操作系统层面设置路由规则,或者使用overlay
网络等其他网络模式。 -
主机
可以和容器
通信,容器之间也可以相互通信
-
安装
docker
时会自动创建一个docker0
网桥,运行容器时,你可以使用选项指定容器应连接到哪个
网络,否则Docker
守护程序默认将容器连接到docker0
虚拟网桥,通过docker0
网桥以及Iptables nat
表配置与宿主机通信。 -
Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给docker0 接口。 此后启动的容器内的网口也会自动分配一个同一网段的地址。
docker0的IP地址则为容器的默认网关
。在主机上创建一对虚拟网卡vethpair设备,Docker将veth pair设备的端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中(bridge模式示意图如下图所示)
[root@docker-node1 ~]# nmcli connection
NAME UUID TYPE DEVICE
eth0 3fe4f788-e5f3-4046-8a3e-6cdfb8098aab ethernet eth0
docker0 80889309-7f07-45a6-9f59-cd49caba864d bridge docker0
- 我们可以发现
docker0网卡
的ip地址
为172.17.0.1/16
[root@docker-node1 ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:3eff:fe09:bb64 prefixlen 64 scopeid 0x20<link>
ether 02:42:3e:09:bb:64 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 15 bytes 1866 (1.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.25.254.100 netmask 255.255.255.0 broadcast 172.25.254.255
inet6 fe80::4e21:e4b4:36e:6d14 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:cf:80:f2 txqueuelen 1000 (Ethernet)
RX packets 5180 bytes 2131050 (2.0 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3072 bytes 296398 (289.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 当我们启动一个容器后,我们可以发现它的ip地址为
172.17.0.2/16
,和docker0网卡
的IP
在同一个网段
[root@docker-node1 ~]# docker run -it --name test1 --network bridge busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2042 (1.9 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
- 我们可以发现,容器可以访问宿主机
/ # ping 172.25.254.100
PING 172.25.254.100 (172.25.254.100): 56 data bytes
64 bytes from 172.25.254.100: seq=0 ttl=64 time=0.244 ms
64 bytes from 172.25.254.100: seq=1 ttl=64 time=0.088 ms
64 bytes from 172.25.254.100: seq=2 ttl=64 time=0.105 ms
- 我们也可以发现,容器可以访问外网
/ # ping www.baidu.com
PING www.baidu.com (183.2.172.42): 56 data bytes
64 bytes from 183.2.172.42: seq=0 ttl=127 time=37.890 ms
64 bytes from 183.2.172.42: seq=1 ttl=127 time=38.224 ms
64 bytes from 183.2.172.42: seq=2 ttl=127 time=39.000 ms
[root@server ~]# docker run -d -it --name linux-ubuntu --net=bridge ubuntu
[root@server ~]# docker inspect linux-ubuntu | grep -i network
"NetworkMode": "bridge",
"NetworkSettings": {
"Networks": {
"NetworkID": "69cf9fe45652f27db873a0f1dbcc7f36b7357af33884f51356c4c38f41ca5181",
none模式
- 使用
none模式
,Docker容器
拥有自己的Network Namespace
,但是,并不为Docker容器
进行任何网络配置
。也就是说,这个Docker容器没有网卡
、ip
、路由
等信息,只有lo网络接口
。 不参与网络通信
,运行于此类容器中的进程仅能访问本地lo回环接口
,None模式
示意图如下所示:
- 我们可以发现,只有一个
lo网卡
[root@docker-node1 ~]# docker run -it --name test1 --network none busybox
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
- 不能通信
/ # ping www.baidu.com
ping: bad address 'www.baidu.com'
/ # ping 172.25.254.100
PING 172.25.254.100 (172.25.254.100): 56 data bytes
ping: sendto: Network is unreachable
[root@server ~]# docker run -d --name linux-ubuntu --network=none ubuntu
c2d71a8545314dbf2ef8d936e8c69dc34c02296ecf6c5585d40258ade4e47a80
[root@server ~]# docker inspect linux-ubuntu | grep -i network
"NetworkMode": "none",
"NetworkSettings": {
"Networks": {
"NetworkID": "fa566b41018a2edff899c8bf0b3f275a6726582276241e912d96fc48b626693a",
[root@server ~]#
host模式
- 如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个NetworkNamespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。Host模式示意图如下所示:
[root@server ~]# docker run -it --name linux-ubuntu -d --net=host ubuntu
64bf40afc85615e1af24de8e5062a044e9dd8f4e9149d9b06e2015d6e2aab098
[root@server ~]# docker inspect linux-ubuntu | grep -i network
"NetworkMode": "host",
"NetworkSettings": {
"Networks": {
"NetworkID": "211a8fdf9c39a6ebbbd74c3b88e3e682a645f2d553bb21f8d2f6005fd84582a1",
[root@server ~]#
container模式
Container模式的示例可以如下进行:
首先,我们创建一个新的容器,并默认使用Bridge模式(这也是Docker的默认网络模式)。我们将使用busybox镜像来创建一个名为bb的容器:
docker run -itd --name bb busybox
接下来,我们要创建另一个容器,这次我们将使用Nginx镜像,并通过--net container:bb
参数指定它的网络模式为Container模式,让它和之前创建的bb容器共享相同的网络命名空间:
docker run -d --name nginx-container --net=container:bb nginx
这条命令会启动一个新的Nginx容器,并将其网络配置设置为与bb容器相同。现在,nginx-container和bb容器将共享相同的IP地址和端口范围,它们之间的进程可以通过lo网卡设备进行通信。
[root@server ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
630a7fa66f4c nginx:latest "/docker-entrypoint.…" 53 minutes ago Up 53 minutes 0.0.0.0:32770->80/tcp, :::32770->80/tcp web1
[root@server ~]# docker run -d --name linux-ubuntu --network=container:web1 ubu
ntu
2738e0fec3c329d77b53d08ef04b79650d08dc09cd58db735ccceb9bc2b47379
[root@server ~]# docker inspect linux-ubuntu | grep -i network
"NetworkMode": "container:630a7fa66f4cffb7c17887295af442d8c3fd45e3c5fe9b5497f127474d2cf594",
"NetworkSettings": {
"Networks": {}
[root@server ~]#