Docker 系统性入门+进阶实践-06Docker的网络

网络命名空间、端口映射、网络地址转换、路由等概念会在这一章讲解。

网络常用命令

  1. ip地址的查看
    windows: ipconfig linux: ip addr
  2. 网络连通性测试:
    ping mayanan.cn
  3. 端口连通性测试
    telnet mayanan.cn 80
  4. curl命令:请求web服务的
    curl命令文档
  5. 路径探测跟踪
    traceroot www.mayanan.cn

容器网络涉及到哪些问题?

  1. 容器为什么能获取到ip地址?
  2. 为什么宿主机可以ping通容器的ip?
  3. 为什么容器之间的ip是互通的?
  4. 为什么容器能ping通外网?
  5. 容器的端口转发是怎么回事?

容器间通信bridge模式

  1. 局域网之间电脑如何通信?
  2. 为什么同一台机器上的多个容器ip可以互通?
    因为这些容器都默认连接到了linux bridge桥接网络docker0, docker0就帮助这些容器之间进行ip的通信

容器对外通信之bridge模式

  1. 安装查看linux bridge的命令
    sudo apt-get install -y bridge-utils
  2. 查看当前系统的linux bridge列表
    sudo brctl show
  3. 要想使容器能访问外网,容器所在的宿主机必须能访问外网
  4. linux查看网络中的路由命令
    ip route
  5. iptable转发规则命令
    sudo iptables --list -t nat
  • 容器对外是如何通信的,主要就是借助于iptables,无论是容器与外网通信还是宿主机与外网通信,对于外网来说都是宿主机的公网ip在和他通信,
    因为当容器和外网通信的时候需要进行网络地址转换,容器内的172.18.0.2需要通过linux bridge,例如默认的docker0,在通过docker0转到eth0,
    然后eth0和外网进行通信。

网络知识补充NAT(network address translate)

  1. NAT一般用在路由器上面
    NAT是用来解决IPv4地址不足的问题
    NAT网络地址转换实际上就是从私有到公有,再从公有到私有的转换
    NAT一般是由路由器来实现的。

创建和使用自定义bridge(上)

  1. 创建bridge
    sudo docker network create --driver bridge mybridge
  2. 查看网络
    sudo docker network ls
  3. 查看网络详情
    sudo docker network inspect mybridge
  4. 创建一个容器使用刚刚创建的网络
    sudo docker container run --rm -d --name box3 --network mybridge busybox /bin/sh -c "while true; do sleep 3600; done"
  5. 查看当前容器的详情,同时也能看到使用的network
    sudo docker container inspect box3
  6. 再次查看我们的网络详情
    sudo docker network inspect mybridge
    发现该网段下已经有了一个容器,也就是刚刚创建的box容器
  7. 现在box3和上面创建的box1和box2没有在同一个网络,无法直接通信,可不可以让一个容器同时连接两个网络,答案是:可以的
    为box3增加一个网络连接,连接到docker0这个网络接口也就是默认的bridge这个网络,
    sudo docker network connect bridge box3
  8. 再次查看bridge这个网络详情
    sudo docker network inspect bridge
    发现该网段下多个一个容器,box3
  9. 再次查看box3容器的详情
    sudo docker container inspect box3
    发现box3的networks有两个网络连接了,一个是默认的bridge, 一个是我们自己创建的mybridge,
  10. 此时在通过box3容器去ping容器box1或box2,ping成功了,因为box3已经属于bridge这个网段了
    sudo docker container exec box3 ping 172.18.0.2
  11. 我们可以查看box3容器中的ip地址
    sudo docker container exec box3 ip addr
    我们发现,已经有两个id地址了:
  12. 将一个容器从一个网络中移除
    sudo docker network disconnect bridge box3

创建和使用自定义bridge(下)

  1. 我们在创建一个容器,将该容器与box3在同一网段内
    sudo docker container run --rm -d --name box4 --network mybridge busybox /bin/sh -c "while true; do sleep 3600; done"
    因为box3和box4在同一个linux bridge下面的mybridge里,又因为mybridge是我们自己定义的,
    所以box3和box4可以通过该容器名进行互相ping通
    sudo docker container exec box4 ping box3
    这样是可以ping通的,box1和box2虽然都在默认的bridge下面,因为不是自定义的,所以box1和box2不能通过容器名ping,只能通过对应的ip地址ping通。
  • 总结:这说明了自定义的mybridge有dns的功能,可以帮我们把容器名解析为对应的ip地址;而默认的bridge不具有dns的功能。
  1. 创建network网络时,可以自定义bridge、gateway、subnet等
    sudo docker network create --driver bridge --subnet 192.168.1.0/24 --gateway 192.168.1.1 demo
    查看network详情
    sudo docker network inspect demo
    创建2个容器使用该网络
sudo docker container run --rm -d --name box5 --network demo busybox /bin/sh -c "while true; do sleep 3600; done"
sudo docker container run --rm -d --name box6 --network demo busybox /bin/sh -c "while true; do sleep 3600; done"

查看demo网络下的容器
sudo docker network inspect demo

容器的端口转发

  • 容器内部访问外网的话,需要通过NAT网络地址转换,走默认的网络bridge或者自定义的网络mybridge
  • 外网访问容器内部的话,需要通过端口映射/容器端口转发
  1. 启动nginx容器服务,进行端口映射
    sudo docker container run --rm -it -p 8080:80 nginx
    注意:8080是对外提供的端口,80是容器内部使用的端口
  2. 为什么通过-p就可以实现8080到80端口的转发?
    实际上还是iptables在起作用
    sudo iptables -t nat -nvxL

端口转发和Dockerfile

Dockerfile文件:

FROM python:3.9-slim

WORKDIR /usr/src/app

COPY app /usr/src/app

RUN bash run.sh

EXPOSE 5000

ENTRYPOINT ["flask", "run"]
CMD ["-h", "0.0.0.0"]

EXPOSE的作用就是告诉使用该镜像的用户,此端口是向外暴露的。

host网络详解

  1. 创建两个busybox容器,一个使用bridge网络,另一个使用host网络
sudo docker container run -d --rm --name box1 busybox /bin/sh -c "while true; do sleep 3600; done"
sudo docker container run -d --rm --name box2 --network host busybox /bin/sh -c "while true; do sleep 3600; done"
  1. 查看新建的两个容器的ip地址
sudo docker exec box1 ifconfig
sudo docker exec box2 ifconfig

所谓的host网络也就是说容器与我们的主机采用同一个网络,而bridge网络则是单独的网络
3. 我们创建一个none网络类型的容器
sudo docker container run --rm -d --name box1 --network none busybox /bin/sh -c "while true; do sleep 3600; done"
查看该容器的网络
sudo docker container exec box1 ip addr
我们发现它只有一个lo会还网卡,没有其它的网络,应用场景式,当我们使用容器编排工具的时候,
如果我们希望docker只为我们创建一个容器,我们自己为该容器配置网络时,none就用上了。

linux网络命名空间

  1. linux的Namespace(命名空间)技术是一种隔离技术,常用的Namespace有user namespace、process namespace、network namespace
    在docker容器中,不同的容器通过network namespace进行了网络隔离,也就是不同的容器有各自的IP地址,路由表,互不影响
  2. 容器技术特别依赖于底层的linux技术,如:linux中namespace资源隔离、cgroup限制资源的消耗等
  3. 测试实验网络命名空间

    创建bridge:
sudo brctl addbr mydocker0
sudo brctl show

准备一个shell脚本:
脚本名字:add-ns-to-br.sh
脚本内容:

#!/bin/bash

bridge=$1
namespace=$2
addr=$3

vethA=veth-$namespace
vethB=eth00

sudo ip netns add $namespace
sudo ip link add $vethA type veth peer name $vethB

sudo ip link set $vethB netns $namespace
sudo ip netns exec $namespace ip addr add $addr dev $vethB
sudo ip netns exec $namespace ip link set $vethB up

sudo ip link set $vethA up

sudo brctl addif $bridge $vethA

脚本执行:

sh add-ns-to-br.sh mydocker0 ns1 172.16.1.1/16
sh add-ns-to-br.sh mydocker0 ns2 172.16.1.2/16

把mydocker0这个bridge up起来:
sudo ip link set dev mydocker0 up
验证:
参考文档

  • 当我们创建了一个docker container的时候,背后肯定是有一个网络命名空间的。
posted @ 2022-05-29 11:34  专职  阅读(98)  评论(0编辑  收藏  举报