Docker网络
一、外部访问容器
'容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p参数来指定端口映射'
当使用 "-P" 参数时,Docker 会随机映射一个端口到内部容器开放的网络端口
# 使用Docker container ls 可以看到,本地主机的8080端口被映射到容器的80端口。此时访问本机的8080端口即可访问容器内的nginx页面
[root@docker ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ccd35baec11b nginx "/docker-entrypoint.…" 23 hours ago Up 3 hours 0.0.0.0:8080->80/tcp mario
# 同样的可以使用 docker log 命令来查看访问记录
[root@docker ~]# docker logs ccd35
192.168.5.2 - - [24/Oct/2021:06:01:40 +0000] "GET / HTTP/1.1" 200 1703 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0" "-"
'注意'
-p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器(毕竟主机的端口也是唯一的)。支持的格式有以下几种
ip:hostport:containerport | ip::containerport | hostport:containerport
1.1 映射所有接口地址
使用 hostport:containerport 格式将本地的80端口映射到容器的80端口
[root@docker ~]# docker run -d -p 80:80 --name nginx nginx
3b41c993fd08782181e80c9a66333af1312fdb519733ef04f36c5a7e6945bbca
[root@docker ~]#
[root@docker ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3b41c993fd08 nginx "/docker-entrypoint.…" 6 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp nginx
'此时默认会绑定本地所有接口上的所有地址,即可以访问宿主机所有的ip地址的80端口进行访问容器内的内容'
1.2 映射到指定地址的指定端口
使用 ip:hostport:containerport 格式指定映射使用一个特定地址,如下所示
[root@docker ~]# docker run -d -p 172.16.5.230:80:80 --name nginx nginx
8bb384baa107a809e579ad6797e97f11b63f0fa07af87cfd8700731e517b7d87
[root@docker ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8bb384baa107 nginx "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 172.16.5.230:80->80/tcp nginx
'此时只能通过172.16.5.230这个ip的80端口进行访问容器内的nginx'
1.3 映射到指定地址的任意端口
使用 ip::containerport 绑定宿主机的任意端口到容器的80端口,本地主机会自动分配一个端口
root@docker ~]# docker run -d -p 172.16.5.230::80 --name nginx nginx
e9d0074fa8c238c3e6fda33ad0f46537518b60a9f8e36e8d07b0d1fbefede8ce
[root@docker ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e9d0074fa8c2 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 172.16.5.230:4000->80/tcp nginx
'此时为宿主机随机分配一个端口映射到容器内的80端口,而且限制了绑定的ip为172.16.5.230'
# 还可以使用udp标记来指定udp端口
[root@docker ~]# docker run -d -p 172.16.5.230:80:80/udp --name nginx nginx
a0d588d376232cf9ee980509a8eb44f364802cf3a07981ed4be6ea9e66e513a8
1.4 查看映射的端口配置
'可使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址'
[root@docker ~]# docker port nginx
80/udp -> 172.16.5.230:80
'注意'
1. 容器有自己的内部网络和ip地址( 使用 docker inspect 查看,docker还可以有一个可变的网络配置)
2. -p选项可以多次使用来绑定多个端口,如下所示
[root@docker ~]# docker run -d -p 80:80 -p 443:443 --name nginx nginx
30ee33cf287ff0169a00869482f497e0281d8cf59f1af659535e8bcad0c2dfcd
[root@docker ~]# docker port nginx
80/tcp -> 0.0.0.0:80
443/tcp -> 0.0.0.0:443
二、网络基础
2.1 网络名称空间
# 为了支持网络协议栈的多个实例,linux在网络协议栈中引入了名称网络空间(Network Namespace),这些独立的协议栈被隔离到不同的命名空间中。处于不同的命名空间的网络协议栈是完全隔离的,彼此之间无法进行网络通信,就好像两个"平行宇宙"。通过这种对网络资源的隔离,就能在一个宿主机上虚拟多个不同的网络环境
1) 创建一个命名空间
[root@docker ~]# ip netns add test01
[root@docker ~]# ip netns add test02
[root@docker ~]#
[root@docker ~]#
[root@docker ~]# ip netns list
test02
test01
2.2 Veth设备
'Veth是Linux中一种虚拟出来的网络设备,veth设备总是成对出现,所以一般也叫veth-pair。其作用是反转数据流方向'
'例如'
如果v-a和v-b是一对veth设备,v-a收到的数据会从v-b发出。相反,v-b收到的数据会从v-a发出。其实说白了,Veth就是一根"网线",你从一头发数据,当然就从另一头接收到数据流,网线的作用就是如此,veth也一样,把数据通过一头"复制"到另一头
1) 创建Veth设备对
[root@docker ~]# ip link add veth type veth peer name veth001
[root@docker ~]# ip link show
28: veth001@veth: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 9a:0d:3d:0d:75:0b brd ff:ff:ff:ff:ff:ff
29: veth@veth001: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether be:36:06:8e:32:e9 brd ff:ff:ff:ff:ff:ff
'通过ip link show 命令可以看到生成了两个veth设备,互为对方的peer'
2) 绑定命名空间
[root@docker ~]# ip link set veth001 netns test01
[root@docker ~]# ip link show | grep veth
16: veth80f688f@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
21: vethfaa4140@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-079a9bb8194b state UP mode DEFAULT group default
27: vethaa46204@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
29: veth@if28: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
'此时使用 ip link show 已经看不到veth001了,但是当我们进入到test01的时候就可以看到了'
[root@docker ~]# ip netns exec test01 bash
[root@docker ~]# ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
28: veth001@if29: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 9a:0d:3d:0d:75:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
3) 将veth分配IP
# 设置IP地址
[root@docker ~]# ip netns exec test01 ip addr add 172.16.20.111/20 dev veth001
# 绑定
[root@docker ~]# ip netns exec test01 ip link set dev veth001 up
# 查看
[root@docker ~]# ip netns exec test01 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
28: veth001@if29: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
link/ether 9a:0d:3d:0d:75:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.16.20.111/20 scope global veth001
valid_lft forever preferred_lft forever
'此时双方就互通了'
4) 查看对端Veth设备
'要先退出到宿主机这里~~'
[root@docker ~]# ip netns exec test01 ethtool -S veth001
NIC statistics:
peer_ifindex: 29
[root@docker ~]# ip a | grep 29
29: veth@if28: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
5) 为对端Veth设备设置IP
[root@docker ~]# ip addr add 172.16.20.112/20 dev veth
[root@docker ~]# ip link set dev veth down
[root@docker ~]# ip link set dev veth up
6) 测试连接状态
[root@docker ~]# ip a | grep veth
inet 172.16.20.112/20 scope global veth
[root@docker ~]# ping 172.16.20.111
PING 172.16.20.111 (172.16.20.111) 56(84) bytes of data.
64 bytes from 172.16.20.111: icmp_seq=1 ttl=64 time=0.209 ms
# 进入网络名称空间test01测试
[root@docker ~]# ip netns exec test01 bash
[root@docker ~]# ip a | grep veth
28: veth001@if29: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
inet 172.16.20.111/20 scope global veth001
[root@docker ~]# ping 172.16.20.112
PING 172.16.20.112 (172.16.20.112) 56(84) bytes of data.
64 bytes from 172.16.20.112: icmp_seq=1 ttl=64 time=0.025 ms
2.3 网桥
linux可以支持多个不同的网络,它们之间能够相互通信,就需要一个网桥。网桥是二层的虚拟网络设备,他是把若干个网络接口"连接"起来,从而报文能够互相转发。网桥能够解析收发的报文,读取目标MAC地址的信息,和自己记录的MAC表集合,来决定报文的转发目标网口
2.4 相关网络的基本功能
设备 | 作用总结 |
---|---|
Network Namespace | 主要提供了关于网络资源的隔离,包括网络设备、ipv4和ipv6协议栈、ip路由表、防火墙、/proc/net目录、/sys/class/net 目录、端口(socker)等 |
Linux Bridge | 功能相当于物理交换机,为连在其上的设备(容器)转发数据帧。如docker0网桥 |
Iptables | 主要为容器提供NAT以及容器网络安全 |
Veth Pair | 两个虚拟网卡组成的数据通道。在Docker中,用于连接Docker 容器和Linux Bridge。一端在容器中作为eth0网卡,另一端在Linux Bridge中作为网桥的一个端口 |
三、Docker网络模式
# docker使用linux桥接的方式,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器的一个IP地址,称为Container-IP, 同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
# Docker 网桥是宿主主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即 docker run创建容器的时候通过
Docker 网络模型 | 配置 | 说明 |
---|---|---|
Host模式 | --network=host | 容器和宿主机共享Network Namespace |
Containe模式 | --network=container:ID | 容器和另外一个容器共享Network Namespace。Kubernetes中的pod就是多个容器共享一个Network Namespace |
none模式 | --network=none | 容器有独立的Network Namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,配置IP等 |
bridge模式 | --network=bridge | 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。(默认为该模式) |
3.1 HOST模式
# 如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的
'使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是 docker host 上已经使用的端口就不能再用了,网络的隔离性不好'
# 1. 生成nginx容器,并将其网络模式设置为host模式
[root@docker ~]# docker run -d --name my-web --network host nginx
# 2. 查看生成的容器
[root@docker ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ac5c5746d4c6 nginx "/docker-entrypoint.…" 6 minutes ago Up 6 minutes my-web
# 3. 由于host模式与宿主机共用一个网卡,所以测试访问本机80端口是否可以访问到nginx
[root@docker ~]# curl 127.0.0.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
... ...
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
3.2 Containe模式
# 这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信
# 1. 根据镜像busybox新建并启动容器test01 (linux命令合集软件)
[root@docker ~]# docker run -itd --name test01 busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
24fb2886d6f6: Pull complete
Digest: sha256:f7ca5a32c10d51aeda3b4d01c61c6061f497893d7f6628b92f822f7117182a57
Status: Downloaded newer image for busybox:latest
e7c24988312589642e7c3884306ef5144b85f646f5f7385cc12c4a18ea5c7377
# 2. 再次新建一个容器test02,并将其网络模式设置为containe,使其与test01共享一个网络空间
[root@docker ~]# docker run -itd --name test02 --network "container:test01" busybox
6a337d2d80a4c088e8218349a9a77eeee11ec1dce82dbb6288e2b395b6bb8fc1
# 3. 进入test02以及test01查看ip是否一致~
'test02的IP地址为172.17.0.2'
[root@docker ~]# docker exec -it test02 ip a
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
30: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
'test01的IP地址也为172.16.0.2'
[root@docker ~]# docker exec -it test01 ip a
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
30: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
'由上即可证明,此时两个容器为共享一个 Network Namespace'
3.3 None模式
# 使用none模式,Docker容器拥有自己的Network Namespace,但是并不为Docker容器进行任何网络配置,也就是说,这个Docker容器没有网卡、ip、路由等信息,需要我们自己为Docker 容器添加网卡、配置IP等
'这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性'
# 1. 根据busybox镜像新建并启动容器,设置名称为test03并将其网络模式修改为none
[root@docker ~]# docker run -tid --name test03 --network none busybox
43c0bc6383a06214bbce044b6aee279d41a86f9d60c67dd4133853be8b1c5867
# 2. 查看test03容器里的网络信息
[root@docker ~]# docker exec -it test03 ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
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)
'由此可发现,此时只有一个lo网卡,相当于做了绝对隔离'
3.4 bridge模式
# 当docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式与物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
# 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看
'bridge模式时docker的默认网络模式,不写--network参数,就是bridge模式,使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -nvl查看'
# 根据镜像busybox新建并启动名为test04的容器
[root@docker ~]# docker run -itd --name test04 busybox
55bd22e9fd05c0f564729bdd5f9cbf2b5775e5b57a2da3f167900b0423b44e21
# 查看本机网络状态
[root@docker ~]# ip a
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:85:be:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.5.230/24 brd 192.168.5.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe85:bed9/64 scope link
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:54:5a:16:df 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::42:54ff:fe5a:16df/64 scope link
valid_lft forever preferred_lft forever
# 测试容器内部访问宿主主机的外网网卡
[root@docker ~]# docker exec -it test04 ping 192.168.5.230
PING 192.168.5.230 (192.168.5.230): 56 data bytes
64 bytes from 192.168.5.230: seq=0 ttl=64 time=0.226 ms
64 bytes from 192.168.5.230: seq=1 ttl=64 time=0.066 ms
四、Docker网桥相关命令
4.1 创建网桥
'语法'
docker netwrok create [网络名称]
'案例'
[root@docker ~]# docker network create my-net
b1def42b4379d70d898d98bafb31716fea504596147b67f81de43e7051b11e73
'参数'
-d: 指定网桥类型
4.2 查看网桥
'案例'
[root@docker ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
216ad7ef0568 bridge bridge local
345f9c9bd9e4 host host local
b1def42b4379 my-net bridge local
9c7664c2ccf7 none null local
'参数'
-f: 过滤网桥
[root@docker ~]# docker network ls -f 'driver=bridge'
NETWORK ID NAME DRIVER SCOPE
216ad7ef0568 bridge bridge local
95a9ef3c1dbe my-net bridge local
e039f53f4d99 yuyuyu bridge local
4.3 删除网桥
[root@docker ~]# docker network rm my-net
my-net
'注意: 删除网桥必须是在没有任何应用在使用此网桥'
4.4 查看网桥的详细信息
[root@docker ~]# docker inspect my-net
4.5 连接到一个容器
# 1. 创建一个subnet的网桥
[root@docker ~]# docker network create --subnet 172.22.0.0/16 yuyuyu
e039f53f4d990daf2f250166337e54f46bf2dcea2ebe31bbdda6b9d4ddfad702
# 2. 新建一个容器
[root@docker ~]# docker run --rm -d --name nginx nginx
# 3. 查看容器默认获取到的ip地址
[root@docker ~]# docker inspect -f '{{ .NetworkSettings.Networks.bridge.IPAddress }}' nginx
172.17.0.4
# 4. 指定IP关联上对应的网桥
[root@docker ~]# docker network connect --ip 172.22.0.10 yuyuyu nginx
# 5. 再次查看容器nginx的ip地址
[root@docker ~]# docker inspect -f '{{ .NetworkSettings.Networks.yuyuyu.IPAddress }}' nginx
172.22.0.10
4.6 断开连接
[root@docker ~]# docker network disconnect yuyuyu nginx
[root@docker ~]# docker inspect -f '{{ .NetworkSettings.Networks.yuyuyu.IPAddress }}' nginx
<no value>
4.7 清除所有未被使用到的网桥
[root@docker ~]# docker network prune
WARNING! This will remove all custom networks not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Networks:
my-net
yuyuyu
'参数如下'
-f: 免交互删除
五、容器互联
之前的Docker基本使用 --link 参数来使容器互联,随着Docker网络的完善,还可以使用自定义的Docker网络来连接多个容器
如果有多个容器之间需要互相连接,推荐使用 Docker Compose
5.1 自定义Docker网络
1) 新建网络
[root@docker ~]# docker network create -d bridge my-net
079a9bb8194bc3e145593bfcee8dbdac481ac05ca2a62eb25920be041901c9be
'参数详解'
-d: 此参数指定Docker网络类型,有bridge overlay(其中overlay网络类型用于 Swarm mode)
2) 连接容器
# 1. 运行一个容器并连接到新建的my-net网络
[root@docker ~]# docker run -it --rm --name busybox1 --network my-net busybox sh
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
24fb2886d6f6: Pull complete
Digest: sha256:f7ca5a32c10d51aeda3b4d01c61c6061f497893d7f6628b92f822f7117182a57
Status: Downloaded newer image for busybox:latest
/ #
'参数详解'
docker run: 新建并启动一个容器
-it: 以交互模式启动一个容器
--rm: 添加此参数后,容器退出时就能够自动清理容器内部的文件系统
--name busybox1 : 为该容器指定一个名字
--network my-net: 指定连接所建立的网络
busybox: 镜像名, busybox是一个集成了三百多个linux命令和工具的软件。
sh: 启动容器后执行的命令
3) 打开一个新终端运行一个容器并加入my-net网络
[root@docker ~]# docker run -it --rm --name busybox2 --network my-net busybox sh
/ #
4) 查看当前容器信息
[root@docker ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
24aa5a3331aa busybox "sh" 10 seconds ago Up 10 seconds busybox2
dbac96e99b7a busybox "sh" 11 minutes ago Up 10 minutes busybox1
30ee33cf287f nginx "/docker-entrypoint.…" 30 minutes ago Up 30 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp nginx
5) 使用ping进行测试
# 1. 在busybox1容器中输入以下命令
~ # ip a
... ...
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
... ...
~ # ping busybox2
PING busybox2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.044 ms
# 2. 在busybox2容器中输入以下命令
~ # ip a
... ...
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
... ...
~ # ping busybox1
PING busybox1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.027 ms
'这样,busybox1容器和busybox2容器就建立了互联关系'
六、配置DNS
如何自定义配置容器的主机名和DNS呢 ???? Docker 利用虚拟文件来挂载容器的三个相关配置文件
# 在容器中使用mount命令可以看到挂载信息
/ # mount | grep -e 'host' -e 'resolv'
/dev/mapper/centos-root on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/centos-root on /etc/hostname type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/centos-root on /etc/hosts type xfs (rw,relatime,attr2,inode64,noquota)
'以上这种机制可以让宿主主机DNS信息发生更新后,所有Docker容器的DNS配置通过/etc/resolv.conf文件立刻得到更新'
# 配置全部容器的DNS,也可以在/etc/docker/daemon.json文件中增加以下内容来设置
[root@docker ~]# cat /etc/docker/daemon.json
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
# 再次新建并启动一个容器测试
[root@docker ~]# docker run -it --name ubuntu --rm ubuntu cat /etc/resolv.conf
# Generated by NetworkManager
search 8.8.8.8
nameserver 114.114.114.114
'如果用户想要手动指定容器的配置,可以在使用docker run命令启动容器时加入如下参数'
-h hostanme 或者 --hostname=HOSTNAME 设定容器的主机名,他会被写入到容器内的/etc/hostname 和 /etc/hosts。 但它在容器外部看不到,既不会在 docker container ls中显示,也不会在其他的容器的 /etc/hosts看到。
--dns=IP_ADDRESS 添加DNS服务器到容器的 /etc/resolv.conf中,让容器用这个服务器来解析所有不在/etc/hosts中的主机名
--dns-search=DOMAIN 设定容器的搜索域,当设定搜索与为 .example.com时,在搜索一个名为host的主机时,DNS不仅搜索host,还会搜索host.exa
七、用docker实现部署discuz
需要启动三个容器,php、nginx、mysql
7.1 创建网桥
[root@docker ~]# docker network create discuz
42e7cfa6a93a1025536eb80a3e196e4f7d80150bbd0eabd833500a6d5b1c0195
7.2 部署数据库容器
[root@docker ~]# docker run -d --name mysql --network discuz -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=discuz mysql:5.7
7.3 下载nginx和php镜像
[root@docker ~]# docker pull alvinos/php:wordpress-v2
[root@docker ~]# docker pull alvinos/nginx:wordpress-v2
7.4 修改nginx的配置文件
[root@docker ~]# vim default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
root /usr/share/nginx/html;
location / {
index index.php index.html index.htm;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params;
}
}
7.5 事前准备文件
# 移动代码文件到/opt目录下
[root@docker ~]# mv /root/upload/ /opt/
# 授权
[root@docker ~]# chmod 777 -R /opt/upload/
# 将nginx的配置文件也移动到/opt目录下
[root@docker ~]# mv /root/default.conf /opt/
7.6 新建并启动容器
'php容器'
[root@docker ~]# docker run -d --name php --network discuz -v /opt/upload/:/usr/share/nginx/html alvinos/php:wordpress-v2
'nginx容器'
[root@docker ~]# docker run -d --name nginx --network discuz -v /opt/upload/:/usr/share/nginx/html -v /opt/default.conf:/etc/nginx/conf.d/default.conf -p 8090:80 alvinos/nginx:wordpress-v2
7.7 查看容器状态
[root@docker ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef1a24f6c164 alvinos/nginx:wordpress-v2 "/bin/sh -c 'nginx -…" About a minute ago Up About a minute 443/tcp, 0.0.0.0:8090->80/tcp nginx
66124afc970b alvinos/php:wordpress-v2 "php-fpm -F" 3 minutes ago Up 3 minutes 9000/tcp php
bf671b6ad96d mysql:5.7 "docker-entrypoint.s…" 44 minutes ago Up 44 minutes 3306/tcp, 33060/tcp mysql
7.8 浏览器测试访问
http://192.168.5.230:8090/ # 宿主机的外网网卡IP地址+映射的8090端口