DOcker网络与存储¶
一. Docker的网络¶
1. 查看网络¶
[root@5 docs]# docker network ls
NETWORK ID NAME DRIVER SCOPE
4d823d844712 bridge bridge local
70d882a9147c host host local
e4351f1d76f8 none null local
Docker网络有:
bridge 桥 安装docker后默认创建docker0桥
host 容器的网络空间使用的是宿主机的
none 没有IP地址,不能与外界通讯
Container
2. 启动运行容器时指定的网络模式¶
a. 指定方式是: --network=none
[root@5 docs]# docker run -it --rm --network=none busybox:latest
/ # ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
# 可以看到IP地址只有一个127网段的回环地址,没有IP地址
b. 指定 --network=host
[root@5 docs]# docker run -it --rm --network=host busybox:latest
/ # ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
link/ether 00:0c:29:5a:0f:16 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.103/24 brd 192.168.100.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe5a:f16/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
link/ether 9e:d7:f6:0d:c8:5b brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::9cd7:f6ff:fe0d:c85b/64 scope link
valid_lft forever preferred_lft forever
4: veth35ef695@ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0
link/ether da:95:65:f2:5d:aa brd ff:ff:ff:ff:ff:ff
inet6 fe80::d895:65ff:fef2:5daa/64 scope link
valid_lft forever preferred_lft forever
c. 不指定时候默认使用桥接模式
[root@5 docs]# docker run -it --rm busybox:latest
/ # ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 4e:e3:fa:75:55:fb brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
3. 桥接模式: ‘桥’即为虚拟交换机¶
每当新建一台桥接网络模式的容器就会伴随产生一对接口,其中一个接口在桥上另一个接口在容器上。
我们可以使用brctl show命令查看
# 先把yum源替换为阿里云epel源
# 1. 备份原有yum源头
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
# 2. 下载新repo 到/etc/yum.repos.d/
yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-9.noarch.rpm
sed -i 's|^#baseurl=https://download.example/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel*
sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel*
# 3. 清除缓存然后重新创建缓存
dnf clean all && dnf makecache
# 4. 安装命令
dnf -y install bridgeutils
# 5. 使用命令查看
brctl show
4. 容器间的通信¶
容器在相同宿主机上,利用网桥就可以直接通讯
容器在不同宿主机上,需要借助网络插件(flannel、calico等)实现通讯
5. 容器与外部网络通信¶
容器访问外部网络会利用物理网络的SNAT
外部网络访问容器: 端口映射
-P(大写): 宿主机上会产生一个端口与容器开放的端口进行关联
宿主机产生的端口范围: 由/proc/sys/net/ipv4/ip_local_port_range文件定义
-p(小写): 指定宿主机上的端口与容器开放端口进行关联
格式:
-p 宿主机端口:容器开放端口
-p IP地址:宿主机端口:容器开放端口
[root@5 docs]# docker run --name wev -P -itd nginx:latest
[root@5 docs]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9cc451feaaf4 nginx:latest "/docker-entrypoint.…" 11 seconds ago Up 11 seconds 0.0.0.0:180->80/tcp, [::]:180->80/tcp wev2
d1d70cd3623f nginx:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:32768->80/tcp, [::]:32768->80/tcp wev
cb8013fee1b5 postgres:18-alpine "docker-entrypoint.s…" 2 days ago Up 11 hours 5432/tcp my-pg18-learn
真机在从外部网络访问容器

6. 自定义bridge,并利用此桥运行容器¶
[root@5 docs]# docker network create -d bridge --subnet 10.10.10.0/24 --gateway 10.10.10.1 C149
b9fa8790f0071e7e6c46a4bcbc062732b08084128f386be4ce498ee83ccea288
[root@5 docs]# docker network ls
NETWORK ID NAME DRIVER SCOPE
b9fa8790f007 C149 bridge local
4d823d844712 bridge bridge local
70d882a9147c host host local
e4351f1d76f8 none null local
[root@5 docs]# docker run --name test10 --net=C149 -it --rm busybox:latest
/ # ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether f2:36:a6:28:4e:32 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.2/24 brd 10.10.10.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ping 10.10.10.1
PING 10.10.10.1 (10.10.10.1): 56 data bytes
64 bytes from 10.10.10.1: seq=0 ttl=64 time=0.067 ms
64 bytes from 10.10.10.1: seq=1 ttl=64 time=0.057 ms
64 bytes from 10.10.10.1: seq=2 ttl=64 time=0.058 ms
^C
--- 10.10.10.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.057/0.060/0.067 ms
/ # ping www.baidu.com
^C
/ # exit
[root@5 docs]# docker network rm b9fa8790f
b9fa8790f
# 利用自定义桥运行的容器无法与默认桥运行的容器通信,原因是iptables规则拒绝转发
7. Container模式¶
Container模式使用参数-net=container:名称或ID指定
使用此模式创建的容器需要制定一个已经存在的容器共享网络,而不是和宿主机共享。新创建的容器不会创建自己的网卡,也不会配置自己的IP,而是和一个已经存在的被指定的容器共享IP和端口范围,因此这个容器端口不能和被指定的端口冲突。除了网络之外的文件系统、进程等信息仍然保持相互隔离,两个容器进程可以通过IO网卡和容器IP进行通信。
查看web2的IP地址
[root@5 docs]# docker run -itd --name web2 nginx:latest
e403f68777d8542dce78a3cc60998e95fcf95954231c39cecf56d86554d2bc65
[root@5 docs]# docker inspect web2|grep -C 3 'IPAddress'
"NetworkID": "9609def212fdb6b40efbe0da5bdea9b7a68f246b9ae1ee953db9600805a8426f",
"EndpointID": "3fbe0aa1c6a455631ddf240468ed02e183eed3ee003a2da0fccb1cfa33dd3ddb",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"MacAddress": "7a:3c:fd:23:89:b8",
"IPPrefixLen": 16,
"IPv6Gateway": "",
创建web3,使其与web2使用container网络模式
[root@5 docs]# docker run --name web3 -it --rm --network=container:web2 busybox:latest
/ # ip address list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 7a:3c:fd:23:89:b8 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # exit
结果:
- 容器web3的IP地址与容器web2的地址一致
- 容器web3使用容器web2的网络名称空间
- 容器web3与容器web2共同使用同一个网络名称空间
二. Docker的数据卷¶
1. 数据卷bind mount(容器与宿主机或共享存储来实现数据存储共享)¶
例如: docker run --name test6 -v /test:/data:ro -it --rm busybox:latest
说明:
-v: 创建数据卷
/test: 宿主机或访问共享存储的目录
/data: 容器中的目录,如若不存在则会自动创建
:ro 只读 rw: 可读写
# 先在真机上创建test目录,并在其中写入内容
[root@5 docs]# mkdir /test
[root@5 docs]# echo 'Hello World'>/test/a.txt
# 启动容器并以只读方式挂载真机的/test目录到/data目录
[root@5 docs]# docker run --name test6 -v /test:/data:ro -it --rm busybox:latest
# 以此方式,虚拟机会自动创建/data目录
/ # ls /data
a.txt
# 可以看到刚才在真机中写入的内容
/ # cat /data/a.txt
Hello World
# 尝试在虚拟机中写入内容,因为是只读的,所以失败
/ # echo '111'>/data/b.txt
sh: can't create /data/b.txt: Read-only file system
/ # exit
[root@5 docs]# docker run --name test7 -v /test:/data:rw -it --rm busybox:latest
/ # ls /data
a.txt
/ # echo 'water'>/data/b.txt
/ # exit
[root@5 docs]# cat /test/b.txt
water
2. 数据卷不指定宿主机的位置 docker manage volume -v 容器挂载点(不存在则自动创建)¶
[root@5 docs]# docker run --name test6 -v /data -itd busybox:latest
2b7f61daca333274808fedabd7ed202295f87cef9e4b163cd1eb2aa750cfec58
查看对应容器挂载目录所对应宿主机的位置
[root@5 docs]# docker inspect test6|grep -A 11 'Mounts'
"Mounts": [
{
"Type": "volume",
"Name": "8e9f6dd548f9c4df976ddae96dcec91a756768c2fe3bee88e913c489512fed04",
"Source": "/var/lib/docker/volumes/8e9f6dd548f9c4df976ddae96dcec91a756768c2fe3bee88e913c489512fed04/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
# "Source": "/var/lib/docker/volumes/8e9f6dd548f9c4df976ddae96dcec91a756768c2fe3bee88e913c489512fed04/_data", 这一行就是宿主机与容器挂载目录对应位置
说明:
- docker自动创建的数据卷位于
/var/lib/docker/volume下 - 可以使用 docker inspect 容器的ID号查看到自动创建的数据卷
- 容器删除创建的数据卷也会跟着删除
3. 使用docker volume手动创建数据卷后再挂载到容器中¶
a. 创建数据卷
[root@5 docs]# docker volume create aa
aa
[root@5 docs]# docker volume ls
DRIVER VOLUME NAME
local 8e9f6dd548f9c4df976ddae96dcec91a756768c2fe3bee88e913c489512fed04
local 50afb513f55db09c5a591956125f69b3e093e1eddc8f6acc583de9e30124b605
local 533d999d582bc69bf22177f2fd0d36dfbdcc687214b5342cf5e3d8a4fc9c4c4f
local aa
local e64aa9a57bd828eb783146c061237a982d6f2ff96d77a83c9c039e77d478ad0a
local fdaedb4efd5b2b25496e6a647b32c71e8bb5df1f2148a98a28191e94c8d0c286
local pgdata
# 注: 使用 docker volume prune 可以清理所有没有被容器使用的匿名卷
b. 利用创建的数据卷启动容器
docker run -it --rm -v 数据卷名:/data busybox:latest
说明:
- docker创建的数据卷位于/var/lib/docker/volume/数据卷名;
- 可以使用
docker inspect 容器的ID号查看到创建的数据卷; - 删除容器后创建的数据卷依然存在,可以使用
docker volume rm 数据卷名删除
验证数据是否实现了持久化
[root@5 docs]# docker run --name test04 -it --rm -v aa:/data busybox:latest
/ # ls /data
c.txt
/ # cat /data/c.txt
abcde
/ # exit
删除数据卷
[root@5 docs]# docker volume rm aa
aa
[root@5 docs]# docker volume ls
DRIVER VOLUME NAME
local 8e9f6dd548f9c4df976ddae96dcec91a756768c2fe3bee88e913c489512fed04
local pgdata
4. 容器数据的共享¶
Ⅰ. 容器与宿主之间实现共享
利用数据卷就可以完成数据共享。 -v 宿主机目录:容器挂载目录
Ⅱ. 容器与容器之间数据共享
a: 利用数据卷就可以完成。 -v 宿主机目录:容器挂载目录
不同的容器指定宿主机目录需要一致
b: 数据卷容器(容器直接数据存储)
①: 制作数据卷容器
②: 利用数据卷容器创建新容器testd1
[root@5 docs]# docker run --name test-d1 --volumes-from dbdata -it --rm busybox:latest
/ # ls data/
a.txt b.txt
③: 利用数据卷容器创建新容器testd2(再打开一个新窗口)
[root@5 docs]# docker run --name test-d2 --volumes-from dbdata -it --rm busybox
/ # ls /data
a.txt b.txt
④: 验证test-d1和tst-d2容器之间的数据同步
在test-d2中创建一个新文件
在test-d1容器上可以查看到该文件
总结: 同一台宿主机上不同容器之间数据的共享
- a: 不同容器使用相同宿主机的目录进行挂载
-v 宿主机目录:容器的目录 - b: 不同的容器使用相同宿主机的数据卷
-v 数据卷吗:容器的目录 - c: 将一个容器作为数据卷容器。其他的不同容器使用相同的数据卷容器。 --volumes-from 数据卷容器名