Docker 网络访问
Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。
外部访问容器
容器中可以运行一些网络应用,要让外部也可以访问这些应用。 默认 Docker 会创建一个桥接的网卡 docker0,然后提供了两种网络端口映射方法:
- 随机端口映射 -P 参数
- 指定端口映射 -p 参数
随机端口映射
当使用 -P 参数时,Docker 会随机映射一个端口到内部容器开放的网络端口。
# 运行一个守护态的 nginx 容器,使用随机端口映射
[root@linux-node1 ~]# docker run -d -P nginx
7236cf1a985aff380272cef71683413768738217831b7434cc8829632f4a144b
[root@linux-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7236cf1a985a nginx "nginx -g 'daemon off" 10 seconds ago Up 9 seconds 0.0.0.0:32773->80/tcp, 0.0.0.0:32772->443/tcp adoring_poincare
# 从上面可以看到,本地主机的 32773 端口映射到了容器的 80 端口,32772 端口映射到了容器的 443 端口
# 我们可以通过本地主机的端口来访问对应容器内的应用
# 查看本地主机监听端口
[root@linux-node1 ~]# netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 2240/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2335/master
tcp6 0 0 :::32772 :::* LISTEN 49792/docker-proxy
tcp6 0 0 :::32773 :::* LISTEN 49799/docker-proxy
# 查看 iptables 中 docker 对应的 NAT
[root@linux-node1 ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 2 packets, 130 bytes)
pkts bytes target prot opt in out source destination
117 6012 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 2 packets, 130 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 1 packets, 71 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 LOCAL
Chain POSTROUTING (policy ACCEPT 3 packets, 175 bytes)
pkts bytes target prot opt in out source destination
62 3836 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:443
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:80
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
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32772 to:172.17.0.2:443
2 104 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:32773 to:172.17.0.2:80
# 进入 nginx 容器查看 IP 地址
root@7236cf1a985a:/# ip ad li
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
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
46: eth0@if47: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
# 通过 docker logs 查看 nginx 容器的日志
[root@linux-node1 ~]# docker logs -f 7236cf1a985a
192.168.56.1 - - [18/Sep/2016:11:40:18 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36" "-"
192.168.56.1 - - [18/Sep/2016:11:40:18 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://192.168.56.11:32773/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36" "-"
2016/09/18 11:40:18 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.56.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.56.11:32773", referrer: "http://192.168.56.11:32773/"
随机端口映射可用于测试环境,这样端口没有冲突。
指定端口映射
-p(小写的)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。
支持的格式有 ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort
。
# 运行一个 nginx 容器,指定本地主机上的 80 端口映射到容器的 80 端口
[root@linux-node1 ~]# docker run -d -p 192.168.56.11:80:80 --name mynginx nginx
420066be5a1dce1c19b3c8329177bd320c2657d58559b739a18241602f70d250
[root@linux-node1 ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
420066be5a1d nginx "nginx -g 'daemon off" 2 minutes ago Up 2 minutes 192.168.56.11:80->80/tcp, 443/tcp mynginx
# 使用 docker port 直接查看端口映射情况
[root@linux-node1 ~]# docker port mynginx
80/tcp -> 192.168.56.11:80
# -p 参数可以有多个,示例如下:
[root@linux-node1 ~]# docker run -d -p 82:80 -p 443:443 --name nginxv2 nginx
30fd50542bb541799c688e113f15d0094791822ea2d0370fd1cd86354501f842
[root@linux-node1 ~]# docker port nginxv2
80/tcp -> 0.0.0.0:82
443/tcp -> 0.0.0.0:443
Docker 的网络端口映射是用 NAT 实现,会影响网络性能,在生产环境需要注意。