Docker系列(8) Docker网络(3)-- 单机Docker网络配置
1. 默认网络
当你安装了docker,自动创建了3个网络,可以使用docker network命令来查看
dd@ubuntu04:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
61848f3f9e62 bridge bridge local
6211ead1d40a host host local
47771891e708 none null local
1.1 bridge网络
根据上篇所述,默认情况下,新建的docker会连接到docker0这个网桥上
dd@ubuntu04:~$ ip addr show docker03: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:bc:71:fe:b6 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft forever
dd@ubuntu04:~$ brctl show docker0bridge name bridge id STP enabled interfaces
docker0 8000.0242bc71feb6 no
启动并运行一个容器
dd@ubuntu04:~$ docker run -itd --name dd-test01 ubuntu:18.04 /bin/bash
ce65c0e400e0a7f6b6f10b62d3359ea0ac59abbb6e4ba8f7c938d420b27e65bf
dd@ubuntu04:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce65c0e400e0 ubuntu:18.04 "/bin/bash" 37 seconds ago Up 33 seconds dd-test01
进入容器
dd@ubuntu04:~$ docker exec -it dd-tes01 /bin/bash
查看ip 信息
root@ce65c0e400e0:/# ifconfig
报错:
bash: ifconfig: command not found
解决:
root@ce65c0e400e0:/# apt-get update
root@ce65c0e400e0:/# apt-get install net-tools
查看ip
root@ce65c0e400e0:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)RX packets 2008 bytes 18182532 (18.1 MB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 1853 bytes 104451 (104.4 KB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0loop txqueuelen 1000 (Local Loopback)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
查看网关:
root@ce65c0e400e0:/# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
可以看到test1容器已经获取了一个地址172.17.0.2,和主机的docker0接口地址在同一网络,并将主机的docker0接口地址设置为了网关。
在物理主机上,查看网桥docker0,可以看到已经多了一个接口
dd@ubuntu04:~$ brctl show docker0
bridge name bridge id STP enabled interfaces
docker0 8000.0242bc71feb6 no veth891c3fa
Docker 容器默认使用 bridge 模式的网络特点如下:
- 使用一个 linux bridge,默认为 docker0
- 使用 veth 对,一头在容器的网络 namespace 中,一头在 docker0 上
- 该模式下Docker Container不具有一个公有IP,因为宿主机的IP地址与vethpair的 IP地址不在同一个网段内
- Docker采用 NAT 方式,将容器内部的服务监听的端口与宿主机的某一个端口port进行“绑定”,使得宿主机以外的世界可以主动将网络报文发送至容器内部
- 外界访问容器内的服务时,需要访问宿主机的 IP 以及宿主机的端口 port
- NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。
- 容器拥有独立、隔离的网络栈;让容器和宿主机以外的世界通过NAT建立通信
效果是这样的:
示意图如下:
在物理主机上查看iptables的nat表,可以看到在POSTROUTING链中做了地址伪装:MASQUERADE动作,这样容器就可以通过源地址转换NAT访问外部网络了。
dd@ubuntu04:~$ sudo iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 78 packets, 6004 bytes)pkts bytes target prot opt in out source destination 4 1781 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCALChain INPUT (policy ACCEPT 44 packets, 3501 bytes)pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 430 packets, 32478 bytes)pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCALChain POSTROUTING (policy ACCEPT 430 packets, 32478 bytes)pkts bytes target prot opt in out source destination 9 553 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 Chain DOCKER (2 references)pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
可以使用docker network inspect bridge命令来查看bridge网络情况:
dd@ubuntu04:~$ docker network inspect bridge
[{"Name": "bridge","Id": "61848f3f9e629985880ed98d0293d14b20169e31ef9ed25ffe165439c915042a","Created": "2020-05-07T10:15:11.014764859Z","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": {"ce65c0e400e0a7f6b6f10b62d3359ea0ac59abbb6e4ba8f7c938d420b27e65bf": {"Name": "dd-test01","EndpointID": "14e910d3cc8fbae5820e2a5c1418bffe9d46434ba1688209113ca8323d8b5e3e","MacAddress": "02:42:ac:11:00:02","IPv4Address": "172.17.0.2/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": {}}
]
1.2 none网络模式
网络模式为 none,即不为Docker容器构造任何网络环境,不会为容器创建网络接口,一旦Docker容器采用了none网络模式,那么容器内部就只能使用loopback网络设备,不会再有其他的网络资源。Docker Container的none网络模式意味着不给该容器创建任何网络环境,容器只能使用127.0.0.1的本机网络。
启动一个容器,设为none网络
dd@ubuntu04:~$ docker run -itd --name dd-test02 --network none ubuntu:18.04 /bin/bash
7ae6efef02cfd25bd82c31c94322edfb34c007a741497c85f96e33cbe0cda1b1
进入容器,查看网络情况,发现由于none模式无法联网,导致ipconfig命令无法使用,正好可以复习下前面的命令,我们把bridge模式下的容器导出为image,再以此image创建none模式的container
dd@ubuntu04:~$ docker export ce65c0e400e0 > dd-ubuntu02.tar
dd@ubuntu04:~$ cat dd-ubuntu02.tar | docker import - dd/ubuntu:test
sha256:c332c9fe03b398405c72bc3214a86395853c20c969532074752487ac6d8cb232
dd@ubuntu04:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dd/ubuntu test c332c9fe03b3 6 minutes ago 92.3MB
dd/centos 6.7 c6519f975a25 12 hours ago 191MB
dd/centos dev c6519f975a25 12 hours ago 191MB
dd/ubuntu v2 5b51178018cd 13 hours ago 137MB
dd/ubuntu v1 63cf4e1dfe43 13 hours ago 73.9MB
ubuntu latest 1d622ef86b13 13 days ago 73.9MB
ubuntu 18.04 c3c304cb4f22 13 days ago 64.2MB
httpd latest b2c2ab6dcf2e 2 weeks ago 166MB
ubuntu 14.04 6e4f1fe62ff1 4 months ago 197MB
centos 6.7 9f1de3c6ad53 13 months ago 191MB
ubuntu 15.10 9b9cb95443b5 3 years ago 137MB
training/webapp latest 6fae60ef3446 4 years ago 349MB
ubuntu 13.10 7f020f7bf345 5 years ago 185MBdd@ubuntu04:~$ docker run -itd --network none --name dd-test03 dd/ubuntu:test /bin/bash
2d85c15b3bd8a52c2c9974f4020aa4f4c3ed01d8c5d841fa52b58b44d658d112
dd@ubuntu04:~$ docker exec -it dd-test03 /bin/bash
root@2d85c15b3bd8:/# ifconfiglo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0loop txqueuelen 1000 (Local Loopback)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0root@2d85c15b3bd8:/# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Ifaceroot@2d85c15b3bd8:/# 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
1.3 host网络模式
Host模式并没有为容器创建一个隔离的网络环境。而之所以称之为host模式,是因为该模式下的Docker 容器会和host宿主机共享同一个网络namespace,故Docker Container可以和宿主机一样,使用宿主机的eth0,实现和外界的通信。换言之,Docker Container的IP地址即为宿主机 eth0的IP地址。
其特点包括:
- 这种模式下的容器没有隔离的 network namespace
- 容器的 IP 地址同 Docker host 的 IP 地址
- 需要注意容器中服务的端口号不能与 Docker host 上已经使用的端口号相冲突
- host 模式能够和其它模式共存
示意图:
例如,我们在ubuntu04 的机器上用 host 模式启动一个含有 web 应用的Docker容器,监听 tcp 80 端口。当我们在容器中执行任何类似 ifconfig 命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用192.168.31.204:80 即可,不用任何 NAT 转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
启动容器前,查看物理主机的httpd进程
root@2d85c15b3bd8:/# pgrep httpd
root@2d85c15b3bd8:/#
启动一个容器
dd@ubuntu04:~$ docker run -itd --name dd-net-host --network host dd/ubuntu:test /bin/bash
a96b5b451de7d7df306ff4902f16afb8748fb4e0db808163ba07351088a945fc
进入容器,查看基本信息
dd@ubuntu04:~$ docker exec -it dd-nt-host /bin/bash
root@ubuntu04:/# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255ether 02:42:0a:fd:54:16 txqueuelen 0 (Ethernet)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.31.204 netmask 255.255.255.0 broadcast 192.168.31.255inet6 fe80::20c:29ff:fed0:84b3 prefixlen 64 scopeid 0x20<link>ether 00:0c:29:d0:84:b3 txqueuelen 1000 (Ethernet)RX packets 701 bytes 80060 (80.0 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 402 bytes 51006 (51.0 KB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0inet6 ::1 prefixlen 128 scopeid 0x10<host>loop txqueuelen 1000 (Local Loopback)RX packets 183 bytes 13887 (13.8 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 183 bytes 13887 (13.8 KB)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
root@ubuntu04:/# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.31.2 0.0.0.0 UG 0 0 0 ens33
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.31.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33
安装httpd服务,报错:
root@ubuntu04:/# apt-get install httpd
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package httpd is a virtual package provided by:nginx-light 1.14.0-0ubuntu1.7nginx-full 1.14.0-0ubuntu1.7nginx-extras 1.14.0-0ubuntu1.7lighttpd 1.4.45-1ubuntu3.18.04nginx-core 1.14.0-0ubuntu1.7apache2 2.4.29-1ubuntu4.13yaws 2.0.4+dfsg-2webfs 1.21+ds1-12tntnet 2.2.1-3build1mini-httpd 1.23-1.2build1micro-httpd 20051212-15.1ebhttpd 1:1.0.dfsg.1-4.3build1aolserver4-daemon 4.5.1-18.1aolserver4-core 4.5.1-18.1
You should explicitly select one to install.E: Package 'httpd' has no installation candidate
改装apache2
root@ubuntu04:/# apt-get install apache2
#启动apache2
root@ubuntu04:/# /etc/init.d/apache2 start
root@ubuntu04:/# echo "dd test docker host network" > /var/www/html/index.html
root@ubuntu04:/# exit
退出容器,查看apache2进程
dd@ubuntu04:~$ pgrep apache2
2807
2810
2811
访问主机的80端口,可以访问到容器中的网站服务:
1.4 container 模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
Container 网络模式是 Docker 中一种较为特别的网络的模式。这两个容器之间不存在网络隔离,而这两个容器又与宿主机以及除此之外其他的容器存在网络隔离。
注意:因为此时两个容器要共享一个network namespace,因此需要注意端口冲突情况,否则第二个容器将无法被启动。
示意图:
运行一个容器:查看容器的IP
dd@ubuntu04:~$ docker run -itd --name dd-nt-container01 dd/ubuntu:test /bin/bash
b7de375ff9f423768a70f8eebe9bb93525fb12d8d99f47850da765ebacc6d005dd@ubuntu04:~$ docker exec -it dd-nt-container01 /bin/bash
root@b7de375ff9f4:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)RX packets 18 bytes 1452 (1.4 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0loop txqueuelen 1000 (Local Loopback)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0root@b7de375ff9f4:/# exit
启动另外一个容器,使用dd-nt-container01容器的网络
dd@ubuntu04:~$ docker run -itd --name dd-nt-container02 --network container:dd-nt-container01 dd/ubuntu:test /bin/bash
cfe50ae62a35d5b1d0b9b36ce6180690e024ccd68a1d03925f6c96a199191f8f
进入容器dd-nt-container02,查看网络情况,可以看到两个容器地址信息相同,是共享的
dd@ubuntu04:~$ docker exec -it dd-nt-container02 /bin/bash
root@b7de375ff9f4:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)RX packets 21 bytes 1662 (1.6 KB)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0loop txqueuelen 1000 (Local Loopback)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX packets 0 bytes 0 (0.0 B)TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2. 用户定义网络(User-defined networks)
用户也可以自定义自己的网络。建议使用用户定义的桥接网络来控制容器之间彼此通信,并启用容器名称和IP地址的自动DNS解析,docker默认提供了用于创建这些网络的默认网络驱动程序,可以创建:
- bridge network
- overlay network
- MACVLAN network
- network plugin
- remote network
可以根据需要创建尽可能多的网络,并且可以在任何给定的时间将容器连接到0个或多个网络。此外,还可以在不重新启动容器的情况下连接和断开网络中的运行容器。当容器连接到多个网络时,它的外部连接是通过第一个非内部网络提供的。
2.2 新建网络(bridge networks)
下面先创建一个新的 Docker 网络。
dd@ubuntu04:~$ docker network create -d bridge dd-test-net
dd@ubuntu04:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
db7104d5ad7e bridge bridge local
74a4ffa1c72e dd-test-net bridge local
6211ead1d40a host host local
47771891e708 none null local
参数说明:
- -d:参数指定 Docker 网络类型,有 bridge、overlay。
- 其中 overlay 网络类型用于 Swarm mode,在本节中你可以忽略它。
2.3 连接容器
运行一个容器并连接到新建的 dd-test-net 网络:
dd@ubuntu04:~$ docker run -itd --name test1 --network dd-test-net ubuntu /bin/bash
再运行一个容器并加入到 dd-test-net 网络:
dd@ubuntu04:~$ docker run -itd --name test2 --network dd-test-net ubuntu /bin/bash
查看容器
dd@ubuntu04:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
133b92b9a360 ubuntu "/bin/bash" 2 minutes ago Up 2 minutes test2
ba1dc600a19b ubuntu "/bin/bash" 2 minutes ago Up 2 minutes test1
cfe50ae62a35 dd/ubuntu:test "/bin/bash" 13 minutes ago Up 13 minutes dd-nt-container02
b7de375ff9f4 dd/ubuntu:test "/bin/bash" 15 minutes ago Up 14 minutes dd-nt-container01
733e69a6a919 dd/ubuntu:test "/bin/bash" 37 minutes ago Up 37 minutes dd-nt-host
下面通过 ping 来证明 test1 容器和 test2 容器建立了互联关系。
如果 test1、test2 容器内中无 ping 命令,则在容器内执行以下命令安装 ping
test1:
dd@ubuntu04:~$ docker exec -it test1 /bin/bash
root@ba1dc600a19b:/# ping
bash: ping: command not found
root@ba1dc600a19b:/# apt-get update
root@ba1dc600a19b:/# apt install iputils-ping
root@ba1dc600a19b:/# ping test2
PING test2 (172.18.0.3) 56(84) bytes of data.
64 bytes from test2.dd-test-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.196 ms
64 bytes from test2.dd-test-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.094 ms
64 bytes from test2.dd-test-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.055 ms
64 bytes from test2.dd-test-net (172.18.0.3): icmp_seq=4 ttl=64 time=0.067 ms
test2:
dd@ubuntu04:~$ docker exec -it test2 /bin/bash
root@ba1dc600a19b:/# ping
bash: ping: command not found
root@ba1dc600a19b:/# apt-get update
root@ba1dc600a19b:/# apt install iputils-ping
root@ba1dc600a19b:/# ping test1
PING test2 (172.18.0.3) 56(84) bytes of data.
64 bytes from test1.dd-test-net (172.18.0.2): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from test1.dd-test-net (172.18.0.2): icmp_seq=2 ttl=64 time=0.080 ms
64 bytes from test1.dd-test-net (172.18.0.2): icmp_seq=3 ttl=64 time=0.061 ms
64 bytes from test1.dd-test-net (172.18.0.2): icmp_seq=4 ttl=64 time=0.128 ms
这样,test1 容器和 test2 容器建立了互联关系。
查看网络情况:
dd@ubuntu04:~$ docker network inspect dd-test-net
[{"Name": "dd-test-net","Id": "74a4ffa1c72e8da7f19bf921a97f3c1ac8fd5c74dce3c386c67f21d68dce0470","Created": "2020-05-07T15:17:21.854079137Z","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "172.18.0.0/16","Gateway": "172.18.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"133b92b9a36053c7dd14003a2d1c2bf709b75ce7f01a46dba484f8118dcf5803": {"Name": "test2","EndpointID": "743cc1fdbb4dd0edbcc5f8003bedc934c66cb563374373399f8b7ee5355b28f8","MacAddress": "02:42:ac:12:00:03","IPv4Address": "172.18.0.3/16","IPv6Address": ""},"ba1dc600a19b428d23bfc3031a454bdd6641fd1be2335d79e555a31bb956ff45": {"Name": "test1","EndpointID": "71f41de3865893a3ea300490f2899d4ad6013bb99d38a12a9085234a243cd12b","MacAddress": "02:42:ac:12:00:02","IPv4Address": "172.18.0.2/16","IPv6Address": ""}},"Options": {},"Labels": {}}
]
如果有多个容器之间需要互相连接,推荐使用 Docker Compose,后面会介绍
需要注意创建的网络中的容器必须在同一个HOST主机上,网络中的每个容器都可以立即与网络中的其他容器通信。然而,网络本身将容器与外部网络隔离开来。
在用户定义的网桥网络中,不支持linking。可以在这个网络中公开和发布容器端口,也就是expose and publish
如果你想在单一主机上运行一个相对小的网络,使用桥接网络是有效果的。
然而你想创建一个大网络,可以通过overlay 网络来实现。
3. 外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。
当使用–P(大写)标记时,Docker 会随机映射一个随机的端口到内部容器开放的网络端口。
注:-P使用时需要指定–expose选项或dockerfile中用expose指令容器要暴露的端口,指定需要对外提供服务的端口
从docker hub下载一个httpd镜像
dd@ubuntu04:~$ docker pull httpd
dd@ubuntu04:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dd/ubuntu test c332c9fe03b3 2 hours ago 92.3MB
dd/centos 6.7 c6519f975a25 14 hours ago 191MB
dd/centos dev c6519f975a25 14 hours ago 191MB
dd/ubuntu v2 5b51178018cd 14 hours ago 137MB
dd/ubuntu v1 63cf4e1dfe43 15 hours ago 73.9MB
ubuntu latest 1d622ef86b13 13 days ago 73.9MB
ubuntu 18.04 c3c304cb4f22 13 days ago 64.2MB
httpd latest b2c2ab6dcf2e 2 weeks ago 166MB
ubuntu 14.04 6e4f1fe62ff1 4 months ago 197MB
centos 6.7 9f1de3c6ad53 13 months ago 191MB
ubuntu 15.10 9b9cb95443b5 3 years ago 137MB
training/webapp latest 6fae60ef3446 4 years ago 349MB
ubuntu 13.10 7f020f7bf345 5 years ago 185MB
3.1 -P
使用这个下载的镜像启动一个容器:
dd@ubuntu04:~$ docker run -d -P --name dd-web-test01 httpd
dd@ubuntu04:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d181fd5b896b httpd "httpd-foreground" 9 seconds ago Up 7 seconds 0.0.0.0:32768->80/tcp dd-web-test01
133b92b9a360 ubuntu "/bin/bash" 30 minutes ago Up 30 minutes test2
ba1dc600a19b ubuntu "/bin/bash" 30 minutes ago Up 30 minutes test1
cfe50ae62a35 dd/ubuntu:test "/bin/bash" 41 minutes ago Up 41 minutes dd-nt-container02
b7de375ff9f4 dd/ubuntu:test "/bin/bash" 42 minutes ago Up 42 minutes dd-nt-container01
733e69a6a919 dd/ubuntu:test "/bin/bash" About an hour ago Up About an hour dd-nt-host
可以看到容器的80端口被随机映射到主机的32768端口
访问主机IP地址的32768端口,就可以访问到容器的httpd服务
3.2 -p
-p(小写)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有ip:hostPort:containerPort | ip::containerPort |
hostPort:containerPort
3.2.1 hostPort:containerPort
注意:
- 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量。)
- -p 标记可以多次使用来绑定多个端口
dd@ubuntu04:~$ docker run -d -p 8000:80 --name dd-web-test02 httpd
18b2ff2e1448aa2af0868fb3671f2ea0247229b1f74b5aaecd42f3eaa3dcf31c
dd@ubuntu04:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
18b2ff2e1448 httpd "httpd-foreground" 11 seconds ago Up 10 seconds 0.0.0.0:8000->80/tcp dd-web-test02
d181fd5b896b httpd "httpd-foreground" 6 minutes ago Up 6 minutes 0.0.0.0:32768->80/tcp dd-web-test01
133b92b9a360 ubuntu "/bin/bash" 36 minutes ago Up 36 minutes test2
ba1dc600a19b ubuntu "/bin/bash" 37 minutes ago Up 37 minutes test1
cfe50ae62a35 dd/ubuntu:test "/bin/bash" 47 minutes ago Up 47 minutes dd-nt-container02
b7de375ff9f4 dd/ubuntu:test "/bin/bash" 49 minutes ago Up 49 minutes dd-nt-container01
733e69a6a919 dd/ubuntu:test "/bin/bash" About an hour ago Up About an hour dd-nt-host
可以看到主机的8000端口已经和容器dd-web-test002的80端口做了映射
访问主机的8000端口
3.2.2 ip:hostPort:containerPort
映射到指定地址的指定端口
可以使用 ip:hostPort:containerPort 格式,指定映射使用一个特定地址,比如宿主机网卡
配置的一个地址192.168.31.204
dd@ubuntu04:~$ docker run -d -p 192.168.31.204:18000:80 --name dd-web-test03 httpd
a6f4f1fcf8e535c4c6c6150a44282ff6c3913f42fcaaf117dc56e4c5c2dbdb58
dd@ubuntu04:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a6f4f1fcf8e5 httpd "httpd-foreground" 39 seconds ago Up 38 seconds 192.168.31.204:18000->80/tcp dd-web-test03
18b2ff2e1448 httpd "httpd-foreground" 7 minutes ago Up 7 minutes 0.0.0.0:8000->80/tcp dd-web-test02
d181fd5b896b httpd "httpd-foreground" 13 minutes ago Up 13 minutes 0.0.0.0:32768->80/tcp dd-web-test01
133b92b9a360 ubuntu "/bin/bash" 43 minutes ago Up 43 minutes test2
ba1dc600a19b ubuntu "/bin/bash" 44 minutes ago Up 44 minutes test1
cfe50ae62a35 dd/ubuntu:test "/bin/bash" 54 minutes ago Up 54 minutes dd-nt-container02
b7de375ff9f4 dd/ubuntu:test "/bin/bash" 56 minutes ago Up 56 minutes dd-nt-container01
733e69a6a919 dd/ubuntu:test "/bin/bash" About an hour ago Up About an hour dd-nt-host
3.2.3 ip::containerPort
使用 ip::containerPort 绑定192.168.31.204的任意端口到容器的80端口,本地主机会自动分配一个口。这里就不再掩饰
注:还可以使用 udp 标记来指定 udp 端口
dd@ubuntu04:~$ docker run -d -p 192.168.31.204::80/udp --name dd-web-test04 httpd
df4d8a3e3ac16d4e5474fe110fe340ec2edc4f0d8dd997404ed81181dc326a70
dd@ubuntu04:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
df4d8a3e3ac1 httpd "httpd-foreground" 7 seconds ago Up 6 seconds 80/tcp, 192.168.31.204:32768->80/udp dd-web-test04
a6f4f1fcf8e5 httpd "httpd-foreground" 3 minutes ago Up 3 minutes 192.168.31.204:18000->80/tcp dd-web-test03
18b2ff2e1448 httpd "httpd-foreground" 10 minutes ago Up 10 minutes 0.0.0.0:8000->80/tcp dd-web-test02
d181fd5b896b httpd "httpd-foreground" 16 minutes ago Up 16 minutes 0.0.0.0:32768->80/tcp dd-web-test01
133b92b9a360 ubuntu "/bin/bash" 46 minutes ago Up 46 minutes test2
ba1dc600a19b ubuntu "/bin/bash" 47 minutes ago Up 47 minutes test1
cfe50ae62a35 dd/ubuntu:test "/bin/bash" 57 minutes ago Up 57 minutes dd-nt-container02
b7de375ff9f4 dd/ubuntu:test "/bin/bash" 59 minutes ago Up 59 minutes dd-nt-container01
733e69a6a919 dd/ubuntu:test "/bin/bash" About an hour ago Up About an hour dd-nt-host
查看映射端口配置
使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址
dd@ubuntu04:~$ docker port dd-web-test04
80/udp -> 192.168.31.204:32768
3.3 端口映射与iptables
docker端口映射实质上是在iptables 的nat表中添加了DNAT规则
dd@ubuntu04:~$ sudo iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt in out source destination 27 1693 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCALChain INPUT (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 6 packets, 441 bytes)pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCALChain POSTROUTING (policy ACCEPT 6 packets, 441 bytes)pkts bytes target prot opt in out source destination 14 866 MASQUERADE all -- * !br-74a4ffa1c72e 172.18.0.0/16 0.0.0.0/0 0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 0 0 MASQUERADE tcp -- * * 172.17.0.3 172.17.0.3 tcp dpt:800 0 MASQUERADE tcp -- * * 172.17.0.4 172.17.0.4 tcp dpt:800 0 MASQUERADE tcp -- * * 172.17.0.5 172.17.0.5 tcp dpt:800 0 MASQUERADE udp -- * * 172.17.0.6 172.17.0.6 udp dpt:80Chain DOCKER (2 references)pkts bytes target prot opt in out source destination 0 0 RETURN all -- br-74a4ffa1c72e * 0.0.0.0/0 0.0.0.0/0 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 240 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32768 to:172.17.0.3:802 120 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8000 to:172.17.0.4:800 0 DNAT tcp -- !docker0 * 0.0.0.0/0 192.168.31.204 tcp dpt:18000 to:172.17.0.5:800 0 DNAT udp -- !docker0 * 0.0.0.0/0 192.168.31.204 udp dpt:32768 to:172.17.0.6:80
4. 参考文献
[1] docker 网络配置
[2] Docker系列之七:Docker网络
[3] Docker基础 :网络配置详解
[4] Docker 学习 | 第六篇:容器网络配置
[5] Docker的网络配置
[6] 使用 Docker 容器网络
[7] docker 之网络配置
[8] Docker网络详解
[9] docker网络模型之—Container模式
[10] Ubuntu下apache2启动、停止、重启、配置
[11] Ubuntu16.04安装httpd
[12] Ubuntu下解决ifconfig command not found的办法
Docker系列(8) Docker网络(3)-- 单机Docker网络配置相关推荐
- Docker系列(二十四)——Docker实例六Docker安装Redis实例
< Docker实例三Docker安装Redis实例 > 前言 在前面一篇文章种,完成了 < Docker安装MongoDB实例 >,本篇将继续镜像安装教程,并完成Docker ...
- docker系列之在win7上安装docker
当VS Code上出现sql server连接成功的提示,我像是完成了一件大事一样. 前一阵,她让我装个sql server玩玩,我心想,这还不是小意思么,恰好那会我又在看docker,docker里 ...
- Docker系列之八:在Dockerfile中使用多段构建Muti-stage build
系列链接 Docker系列之一:Docker介绍及在Ubuntu上安装 Docker系列之二:Docker 入门 Docker系列之三:使用Docker镜像和仓库 Docker系列之四:Dockerf ...
- Docker系列之三:使用Docker镜像和仓库
系列链接 Docker系列之一:Docker介绍及在Ubuntu上安装 Docker系列之二:Docker 入门 Docker系列之三:使用Docker镜像和仓库 Docker系列之四:Dockerf ...
- Docker系列之五:Volume 卷的使用——以Redis为例
系列链接 Docker系列之一:Docker介绍及在Ubuntu上安装 Docker系列之二:Docker 入门 Docker系列之三:使用Docker镜像和仓库 Docker系列之四:Dockerf ...
- docker 获取宿主机ip_Docker基础修炼6——网络初探及单机容器间通信
如果觉得文章有帮助,欢迎点击头像关注我获取更多原创文章,同时也欢迎转发. 同时也可以在我的历史文章中找到Linux操作系统相关的服务器运维管理入门系列文章,欢迎交流. 前文演示docker容器内部数据 ...
- Docker系列文-----Docker的网络类型(4)
Docker系列文-----Docker的网络类型(4) Docker里的常见文件及作用 Docker 内部的网络类型 1.桥接模式(默认): 2.host模式: 3.container模式 4.no ...
- Docker系列教程15-Docker容器网络
原文:http://www.itmuch.com/docker/15-docker-network/ 本文是篇翻译.原文:https://docs.docker.com/engine/userguid ...
- 【Docker系列】Docker的网络
问题 容器为什么能获取到IP地址? 为什么宿主机可有ping通容器的IP? 为什么容器之间的IP是互通的? 为什么容器能ping通外网? 容器的端口转发是怎么回事? Docker Bridge 网络 ...
- 小白都能懂的 玩转docker系列之 Docker网络详解(超详细)
首先移掉之前所有的容器: [root@xiaoxiao tomcat]# docker rm $(docker ps -aq) fcfddcab1789 [root@xiaoxiao tomcat]# ...
最新文章
- java redis缓存理解_Java项目中使用Redis缓存案例
- GPS-nmealib学习
- tableau地图城市数据_优阅达“优分享” | Tableau 2020.4 “地图标记层” 的多种妙用...
- boost::mpl模块实现deque相关的测试程序
- webservice gsoap 小记
- ijcai statistics
- 过年了,是不是应该写点代码祝福别人
- 公众号开发 单独 给某个用户 推送消息_韩国5G用户6月底已达134万 较5月底增加近70%...
- java基础知识系列---垃圾收集
- gettid()和pthread_self()的区别
- 国产GPGPU如何赶超国外?这3条路最有希望
- 书生中学计算机应用自费,浙江省台州市书生中学2016-2017学年高二上学期期中考试信息试题 Word版含答案.doc...
- 详解LCD12864显示屏的使用(并行控制)
- 网易游戏(雷火)一、二、三交叉面
- parse_url() vul
- 基于MATLAB GUI的指纹识别系统
- vue组件通信1:父传子(props)
- 给公司取名的一些原则
- 61二次型—— 化二次型为标准形、矩阵的合同变换求二次型的标准形
- 微软 奥尔良 游戏服务器,去了新奥尔良,才知道是一个城市,别只知道奥尔良烤翅...