Docker(三)存储持久化、自定义网桥、端口映射
一、存储持久化
docker容器不保存任何数据
重要数据可以使用外部卷存储(数据持久化)
容器可以映射真实主机目录或共享存储为卷
将外部卷映射到容器中提供持久化存储(规则:目录不存在就自动创建;目录存在就直接覆盖掉。语法:docker run -v 外部目录:容器目录 -it 容器名:标签 bash)
外部卷可以给多个容器映射使用,这种方式可以解决容器间共享问题
因此,可以使用以下方式实现不同宿主机上的容器之间文件共享问题:
部署NFS服务:
[root@node1 ~]# yum install -y nfs-utils
root@node1 ~]# mkdir /var/webroot
[root@node1 ~]# chmod 777 /var/webroot/
[root@node1 ~]# vim /etc/exports #表示将本地/var/webroot目录作为共享磁盘,使用权限为可读可写
/var/webroot *(rw)
[root@node1 ~]# systemctl start nfs
[root@node1 ~]# systemctl enable nfs
挂载并使用nfs(Docker1节点):
[root@docker1 ~]# yum install -y nfs-utils
[root@docker1 ~]# showmount -e 192.168.0.30 #查看192.168.0.30上可远程挂载的nfs
Export list for 192.168.0.30:
/var/webroot *
[root@docker1 ~]# mount -t nfs 192.168.0.30:/var/webroot /mnt #挂载远程磁盘到/mnt
[root@docker1 ~]# docker run -itd -v /mnt:/var/www/html myos:httpd #将宿主机/mnt目录映射到容器的/var/www/html目录
[root@docker1 ~]# vim /mnt/index.html #在宿主机的/mnt下新建一个index页面,内容为akakak
akakak
[root@docker1 ~]# curl 172.17.0.3 #查看容器发布的http内容变为了akakak
akakak
挂载并使用nfs(Docker2节点):
[root@docker2 ~]# yum install -y nfs-utils
[root@docker2 ~]# mount -t nfs 192.168.0.30:/var/webroot /mnt
[root@docker2 ~]# docker run -itd -v /mnt:/var/www/html 192.168.0.30:50000/myos:httpd #从镜像仓库创建并运行http容器
[root@docker2 ~]# echo bsbsbs>/mnt/index.html
[root@docker2 ~]# curl 172.17.0.2
bsbsbs
因此,如果有多个http容器的话,只需要在一个Docker节点改变挂载目录下的index文件内容就可以改变所有http容器发布的内容,同时这个index还可以永久保存到nfs服务器上,即使容器坏了也不会消失。
二、自定义网桥
1.查看Docker默认网络模型
[root@docker1 ~]# ifconfig #docker0是一个虚拟交换机,是docker1节点内部容器通讯的时候使用的
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
ether 02:42:b7:d6:4a:f3 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.0.31 netmask 255.255.255.0 broadcast 192.168.0.255
inet6 fe80::20c:29ff:fe2a:55a4 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:2a:55:a4 txqueuelen 1000 (Ethernet)
RX packets 89 bytes 9889 (9.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 88 bytes 9783 (9.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@docker1 ~]# docker network list #查看目前docker拥有的三种网络:桥接、仅主机、无网络
NETWORK ID NAME DRIVER SCOPE
e89744497199 bridge bridge local
63d168300e6d host host local
6d799d00b906 none null local
如果容器想使用docker0之外的网络(目前docker0的网段都在172.17.0.x),则需要新建一个docker1虚拟交换机,docker1和docker0内部的网络是隔离开来的。
#演示1:
要求:1.容器1与容器2可以互通;2.容器3与容器4能够互通;3.容器(12)和容器(34)不能互通
方案:新建Docker网络模型
[root@docker1 ~]# docker network create --subnet=10.10.10.0/24 docker1 #subnet指定在这个网络下创建的容器IP为10.10.10.x,docker1是新的虚拟交换机名称
[root@docker1 ~]# ip a #br-d40848f600db就是新的虚拟交换机docker1
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:2a:55:a4 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.31/24 brd 192.168.0.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe2a:55a4/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:b7:d6:4a:f3 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
4: br-d40848f600db: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:45:78:63:51 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.1/24 scope global br-d40848f600db
valid_lft forever preferred_lft forever
[root@docker1 ~]# docker network list #使用docker network查看容器网络可以看到docker1
NETWORK ID NAME DRIVER SCOPE
e89744497199 bridge bridge local
d40848f600db docker1 bridge local
63d168300e6d host host local
6d799d00b906 none null local
[root@docker1 ~]# docker run -itd myos:latest #创建容器1,使用默认虚拟交换机docker0
[root@docker1 ~]# docker run -itd myos:latest #创建容器2,使用默认虚拟交换机docker0
查看两个容器IP,均在172.17.0.x网段
[root@docker1 ~]# docker run -itd --network=docker1 myos:latest #创建容器3,--network指定虚拟交换机为docker1,不指定的话默认为docker0
[root@docker1 ~]# docker run -itd --network=docker1 myos:latest #创建容器4,--network指定虚拟交换机为docker1,不指定的话默认为docker0
查看两个容器IP,均在10.10.10.x网段
#这样(12)、(34)两组容器之间就无法通信了,两个虚拟交换机(docker0、docker1)将容器(12)、容器(34)隔离成了两个网络;同时,同一虚拟交换机下的两个容器还是可以通信的(1和2可以通信,3和4可以通信),满足案例要求
作为4个容器的宿主机,依然是可以访问所有容器的:
[root@docker1 ~]# ping 172.17.0.2
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.103 ms
[root@docker1 ~]# ping 172.17.0.3
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.103 ms
[root@docker1 ~]# ping 10.10.10.2
64 bytes from 10.10.10.2: icmp_seq=1 ttl=64 time=0.093 ms
[root@docker1 ~]# ping 10.10.10.3
64 bytes from 10.10.10.3: icmp_seq=1 ttl=64 time=0.093 ms
三、端口映射
如果客户想要访问容器发布的服务,但是又无法ping通容器的IP怎么办呢?我们可以使用-p参数把宿主机端口和容器端口绑定,客户直接访问宿主机的ip加端口就可以访问容器发布的服务了
语法:-p 宿主机端口:容器端口
例如把docker1主机(192.168.0.31)变成http服务主机:
[root@docker1 ~]# docker run -itd -p 80:80 myos:httpd
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现