七、Docker网络-容器的端口转发 - 图1

转发过程

要实现host2能够访问host1的172.17.0.2:80的Nginx服务,需要进行端口转发。
首先host1与host2能够相互ping通。其中host1中的容器(nginx和busybox)可通过docker的NAT(容器ip为私网,宿主机为公网)功能访问到外网,也就能访问到host2。但是host1中两个容器的ip未在host2的路由表中,所以host2不能直接访问到host1的nginx。此时就需要nginx容器和宿主机host1进行端口转发,将内部的80端口映射到宿主机host1的8080端口。这样host2就能通过host1的8080端口访问到host1的nginx80端口了。
docker中使用-p <外网端口>:<内网端口>来实现端口转发,如:docker container run -d --rm --name web -p 8080:80 nginx。此过程中实际是iptables在生效。
查看iptables(iptables -t nat -nvxL | grep -A 5 'Chain DOCKER')信息发现,iptables增加了DNAT(Destination NAT)规则,此规则将宿主机的8080转发为172.17.0.4即容器nginx的80端口
七、Docker网络-容器的端口转发 - 图2

端口转发实战

Note 查看容器的指定信息,可以通过docker container inspect --format '{{detail}}' <container_name>来实现,如docker container inspect --format '{{.NetworkSettings.IPAddress}}' web

  1. 创建nginx容器进行端口转发并查看容器的ip
  • web容器将nginx的80端口映射为宿主机的8080端口
    1. [root@localhost ~]# docker container run -d --rm --name web -p 8080:80 nginx
    2. Unable to find image 'nginx:latest' locally
    3. latest: Pulling from library/nginx
    4. e5ae68f74026: Pull complete
    5. 21e0df283cd6: Pull complete
    6. ed835de16acd: Pull complete
    7. 881ff011f1c9: Pull complete
    8. 77700c52c969: Pull complete
    9. 44be98c0fab6: Pull complete
    10. Digest: sha256:9522864dd661dcadfd9958f9e0de192a1fdda2c162a35668ab6ac42b465f0603
    11. Status: Downloaded newer image for nginx:latest
    12. a155f83b05ffae86bfe37db7f095d831c07c3c2aa401b0013603206e34bdf558
    13. [root@localhost ~]#
    14. [root@localhost ~]# docker container inspect --format '{{.NetworkSettings.IPAddress}}' web
    15. 172.17.0.4
    16. [root@localhost ~]#
    17. [root@localhost ~]# docker run -d --rm --name client busybox /bin/sh -c "while true; do sleep 3600; done"
    18. 82e754694e9ecd5dfe542eeaaccc5882977d30bc6e58699a5409c66aff08b624
    19. [root@localhost ~]#
    20. [root@localhost ~]# docker container inspect --format '{{.NetworkSettings.IPAddress}}' client
    21. 172.17.0.5
  1. client容器访问web容器并下载对应的html文件

    1. [root@localhost ~]# docker container exec -it client wget http://172.17.0.4
    2. Connecting to 172.17.0.4 (172.17.0.4:80)
    3. saving to 'index.html'
    4. index.html 100% |*****************************************************************************************************| 615 0:00:00 ETA
    5. 'index.html' saved
  2. 宿主机访问本机的8080端口,能够访问到web的nginx

    1. [root@localhost ~]# curl 127.0.0.1:8080
    2. <!DOCTYPE html>
    3. <html>
    4. <head>
    5. <title>Welcome to nginx!</title>
    6. <style>
    7. html { color-scheme: light dark; }
    8. body { width: 35em; margin: 0 auto;
    9. font-family: Tahoma, Verdana, Arial, sans-serif; }
    10. </style>
    11. </head>
    12. <body>
    13. <h1>Welcome to nginx!</h1>
    14. <p>If you see this page, the nginx web server is successfully installed and
    15. working. Further configuration is required.</p>
    16. <p>For online documentation and support please refer to
    17. <a href="http://nginx.org/">nginx.org</a>.<br/>
    18. Commercial support is available at
    19. <a href="http://nginx.com/">nginx.com</a>.</p>
    20. <p><em>Thank you for using nginx.</em></p>
    21. </body>
    22. </html>
  3. 在web端访问宿主机的8080端口

  • 宿主机ip:192.168.226.129

    1. [root@localhost ~]# ip a| grep 192.168
    2. inet 192.168.226.129/24 brd 192.168.226.255 scope global noprefixroute dynamic ens33
  • 访问宿主机的8080端口
    七、Docker网络-容器的端口转发 - 图3

    Dockerfile中的端口暴露

    1. EXPOSE 80

    此语法更多的是解释说明,给使用者解释此镜像使用了80 端口进行映射,即使去掉此语法也能使用-p参数进行端口映射。