0x00 前言
这章还是挺有意思的,解决了前期学习的几个大问题,我创建了容器后,容器如何被主机访问,容器之间是否可以正常访问,不过这章内容讲的比较浅,后面的章节还有具体内容的学习,先来初体验。
0x01 端口映射
端口映射在之前的章节实现中也使用过,属于run
指令中的选项-P
或者-p
,也就是前面所说的暴露端口。
如果在启动容器时不进行暴露端口,在容器外部是无法通过网络来访问容器内的网络应用和服务的,在使用-P
参数时会随机指定49000-49900
中的端口进行映射,拿httpd
来举例
[root@localhost ~]# docker container run -d -P --name http httpd
62714120aebf976310ae684913a7e9e7d0c6501e7b4a7442155ca50d40779693
[root@localhost ~]# docker container port http
80/tcp -> 0.0.0.0:49157
#访问测试,正常访问
[root@localhost ~]# curl localhost:49157
<html><body><h1>It works!</h1></body></html>
也可以使用-p
来进行特定端口的映射
[root@localhost ~]# docker container run -d -p 5080:80 --name http2 httpd
91f7cb39a02eec7f609639907689fda586afc22974b8a9389a4b0aff13464c16
[root@localhost ~]# docker container port http2
80/tcp -> 0.0.0.0:5080
[root@localhost ~]# curl localhost:5080
<html><body><h1>It works!</h1></body></html>
如果有多少个端口需要暴露也可以指定多个,甚至绑定特定IP也可以。
[root@localhost ~]# docker container run -d -p 5081:80 -p 127.0.0.1:81:81 --name http3 httpd
6990991ca1c9c195cf8b53678b8f41b7178206682dc78c07cef2a4e8fecd4913
[root@localhost ~]# docker container port http3
80/tcp -> 0.0.0.0:5081
81/tcp -> 127.0.0.1:81
0x02 互联机制实现便捷互访
容器的互联link
是一种让多个容器中的应用进行快速交互的方式。它会在源和接收容器之间创建连接关系,接收容器可以通过容器名直接访问源容器,而不需要使用特定IP
地址。
#创建两个centos
[root@localhost ~]# docker container run -it -d --name centos1 centos:7 /bin/bash
45e631cbec7d0261d08ab7c7f14f8f6b81eaaaa057455768154d7a472fb7236a
[root@localhost ~]# docker container run -it -d --name centos2 centos:7 /bin/bash
463e58702993998d01665b512ad3b2085e773c91fa12b93605651cc75309bf7d
#没有选择网络,则查看默认网络的IP分配情况,具体原理会在后面章节有讲。
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "8d7a0a2939bcec65c705c12b9ac5aead3aa7ea65e3c5bd64a39ccf8c1bffde45",
"Created": "2021-02-07T12:51:22.673514815+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"45e631cbec7d0261d08ab7c7f14f8f6b81eaaaa057455768154d7a472fb7236a": {
"Name": "centos1",
"EndpointID": "b61bfd3c5f10c2e9f0638ea5e47cd0fe87ab71cd9def68699ef7cddd53c47347",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"463e58702993998d01665b512ad3b2085e773c91fa12b93605651cc75309bf7d": {
"Name": "centos2",
"EndpointID": "b601feeb630d09c92e475f96969552a8286ec3a118fac6c3a556345d9bf49caa",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
#从上可以看到centos1的ip为172.17.0.2,centos2的ip为172.17.0.3。
#测试访问ip
[root@localhost ~]# docker container exec -t centos1 ping -c 1 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.063 ms
--- 172.17.0.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.063/0.063/0.063/0.000 ms
#测试访问容器名
[root@localhost ~]# docker container exec -t centos1 ping -c 1 centos2
ping: centos2: Name or service not known
结果也非常明显,只能通过IP地址互联,假设容器重启后,获取的IP地址变化,则有可能导致环境出现故障,如果是使用容器名进行连接,则可解决这种情况带来的问题,继续测试
#创建新的容器centos3,使用--link互联到centos1上,
[root@localhost ~]# docker container run -it -d --link centos1 --name centos3 centos:7 /bin/bash
#centos3的IP地址为172.17.0.4
[root@localhost ~]# docker network inspect bridge
...
"94670a0bb6826ea05fce2ff9d7d90d336f5c766e9ff312f1bab7f079e86db2f3": {
"Name": "centos3",
"EndpointID": "1af5265372a588afee953275ddc9fd36f76a77ed749ecaab07c93a8e5e0d1e66",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
}
#测试互联,centos1分别使用ip和容器名访问centos3,结果ip能通,容器名不能通。
[root@localhost ~]# docker container exec -t centos1 ping -c 1 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.085 ms
--- 172.17.0.4 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.085/0.085/0.085/0.000 ms
[root@localhost ~]# docker container exec -t centos1 ping -c 1 centos3
ping: centos3: Name or service not known
#测试互联,centos3分别使用ip和容器名访问centos1,结果ip和容器名都能通
[root@localhost ~]# docker container exec -t centos3 ping -c 1 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.064 ms
[root@localhost ~]# docker container exec -t centos3 ping -c 1 centos1
PING centos1 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.060 ms
--- centos1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.060/0.060/0.060/0.000 ms
明显看到--link
是单向的参数,由于只在centos3
做了link
,所以centos1
并不能像centos3
一样,使用容器名进行互访,另外--link
的原理也非常简单,利用着host
文件来进行实现。
#centos3的hosts文件
[root@localhost ~]# docker container exec -t centos3 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 centos1 45e631cbec7d
172.17.0.4 94670a0bb682
#centos1的hosts文件
[root@localhost ~]# docker container exec -t centos1 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 45e631cbec7d
明显可以看到centos3
中对于172.16.0.2
的域名是添加上了容器名centos1
的。
不过这个功能实际上看似好用,但是实际上当我们学过docker高级网络
后,发现其实是不需要用到--link
参数的,可以自动完成!