Docker网络知识

Docker 网络知识

1.使用网络

外部访问容器

容器中可以使用一些网络应用,要让外部也可以访问这些容器,可以通过-P-p参数来指定端口映射。

  当使用-P访问的时候,Docker会随机映射一个端口到内部容器开放的网络端口。
  使用docker container ls可以看到,本地主机的32768被映射到了容器的80端口。此时访问本机的32768端口即可以访问容器内Nginx默认页面

$ docker run -d -P nginx:alpine

$ docker container ls -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
fae320d08268        nginx:alpine        "/docker-entrypoint.…"   24 seconds ago      Up 20 seconds       0.0.0.0:32768->80/tcp   bold_mcnulty

  当然了,我们也可以使用docker logs命令来查看访问记录。

映射所有接口地址

使用hostPort:containerPort格式本地的80端口映射到容器的80端口,可以执行

docker run -d -p 80:80 nginx:alpine

此时会默认绑定本地所有接口上的所有地址

映射到指定地址的指定端口

可以使用ip:hostPort:containerPort格式指定映射使用一个特定的地址,比如localhost地址127.0.0.1

docker run -d -p 127.0.0.1:80 nginx:alpine
映射到指定地址的任意端口

使用ip::containerPort绑定localhost的任意端口到容器的80端口,本地主机会自动分配一个端口

docker run -d -p 127.0.0.1::80 nginx:alpine

还可以使用udp标记来指定udp端口

docker run -d -p 127.0.0.1::80/udp nginx:alpine
查看映射端口配置

使用docker port来查看当前端口的映射配置,也可以查看到绑定的地址

$ docker port fa 80
0.0.0.0:32768

注意:

  • 容器有自己的内部网络和ip地址(使用docker inspect查看,Docker还可以有一个可变的网络配置)
  • -p标记可以多次使用来绑定多个端口

2.容器互联

docker现有的使用手册中,支持使用--link参数来使容器互联。随着Docker网络的完善,建议将容器加入自定义的Docker网络来互联多个容器,而不是使用--link参数

新建网络

先新建一个Docker网络

docker network create -d bridge my-net
运行一个容器并连接到新建的my-net网络
docker run -it --rm --name busybox1 --network my-net busybox sh

docker run -it --rm --name busybox2 --network my-net busybox sh

使用ping命令来验证容器之前的连接性

/ # ping busybox2
PING busybox2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms

3.DNS配置

  Docker利用虚拟文件来挂载容器的3个相关的配置文件,使用mount命令我们可以看到相关的挂载信息
  这种机制可以让宿主主机DNS信息发生更新后,所有Docker容器的DNS配置通过/etc/resolv.conf文件立刻得到更新

4.高级网络配置

这部分我们将介绍Docker的一些高级网络配置和选项

  当Docker启动后,会自动在主机上创建一个docker0虚拟网桥,实际上是Linux一个bridge,可以理解为一个软件交换机,它会在挂载到它的网口之间进行转发。
  同时,Docker随机分配一个本地未占用的私有网段中的一个地址给docker0接口。比如典型的172.17.42.1,掩码为255.255.0.0。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16)的地址。
  当创建一个Docker容器的时候,同时会创建一对veth pair接口(当数据包发送到一个接口的时候,另外一个接口也可以收到相同的数据)。这对接口一端在容器内。即eth0;另一端在本地并被挂载到docker0网桥,名称以veth开头。通过这种方式,主机可以和容器通信,容器之间也可以相互通信。Docker就创建了在主机和所有容器之间的一个虚拟共享网络。
  接下来的部分将介绍在一些场景中,Docker所有的网络定制配置,以及通过Linux命令来调整、补充、甚至替换Docker默认的网络配置

4.1 网桥的连接方式

概念

  网桥是工作在数据链路层的一种网络互连设备,它在互连的LAN之间实现帧的存储和转发,可以连接不同类型的局域网。根据MAC帧的目的地址对收到的帧进行转发。网桥具有过滤帧的功能。当网桥收到一个帧时,并不是向所有的端口转发此帧,而是先检查此帧的目的MAC地址,然后再确定将该帧转发到哪一个端口。
  网络172.17.0.0是Docker默认的Bridge网络的IP地址范围。当Docker创建一个容器时,它会自动分配一个IP地址,这个IP地址是从这个网络范围内选择的。这个网络中的容器可以通过它们的IP地址相互通信。

4.2 快速配置指南

4.3 容器访问控制

  容器的访问控制,主要通过Linux上的iptables防火墙来进行管理和实现,iptables是Linux上默认的防火墙软件,在大部分发行版本中都自带。

容器访问外部网络
sysctl net.ipv4.ip_forward
net.ipv4.ip_forward=1

  这是Linux内核参数,它控制着操作系统是否将转发数据包,从一个网络接口发送到另一个网络接口。当该参数值为0时,表示禁止IP数据包转发;

容器之间相互访问

需要满足以下两方面的支持:

  • 容器的网络拓扑已经互联。默认情况下,所有容器都会被连接到docker0网桥下。
  • 本地系统的防火墙软件-iptables是否允许通过
访问所有端口

  当启动Docker服务的时候,默认会添加一条转发规则到本地主机iptables的FORWARD链上。通过还是禁止取决于选项icc=true(缺省值)
  可见,默认情况下,不同的容器之间是允许网络互通的。如果为了安全考虑,我们可以在/etc/docker/daemon.json文件中配置{"icc":false}来禁止容器之间的网络互通。

访问指定端口

  在通过选项-icc=false关闭网络访问后,还可以通过--link=CONTAINER_NAME:ALIAS选项来访问容器的开放端口。
  例如,在启动Docker服务时,可以同时使用icc=false --iptables=true参数来关闭允许相互的网络访问,并让Docker可以修改系统中的iptables规则。

4.4 端口映射实现

默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。

容器访问外部实现

容器所有到外部网络的连接,源地址都会被NAT成本地系统的IP地址。这是使用iptables的源地址伪装操作实现的

外部访问容器实现

容器允许外部访问,主要是通过端口映射的方式实现的,可以在docker run的时候通过-p或者-P参数启用。

  不管用哪种映射方法,其实也是在本地的iptables的nat表中添加相应的规则。
  使用-P时:(Docker会自动为用户创建端口映射规则)

iptables -t nat -nL
...
Chain DOCKER (2 references)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:49153 to:172.17.0.2:80
  • 'Chain DOCKER’表示这个规则是针对Docker容器的。
  • ‘tcp’表示这个规则只对tcp协议生效
  • ‘0.0.0.0/0’表示允许任意来源的请求
  • ‘tcp dpt:49153’表示匹配目标端口号为49153的TCP请求
  • 'to:172.17.0.2:80’表示将请求重定向到IP地址为172.17.0.2的容器的80端口上。

  综上,这条规则是将主机的49153端口请求转发到Docker内部网络172.17.0.0/16中的某个容器的80端口。
使用-p 80:80时:

$ iptables -t nat -nL
Chain DOCKER (2 references)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80
  • 这里的规则映射了0.0.0.0,意味着将接受主机来自所有接口的流量。

  如果希望永久地绑定在某个固定的ip地址,可以在Docker配置文件/etc/docker/daemon.json中添加如下内容:

{
    "ip": "0.0.0.0
}

4.5 配置docker0网桥

  Docker服务会默认创建一个docker0网桥(其上有一个docker0内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络中。
  Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了MTU(接口允许接受的最大传输单元),通常是1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。
  每次创建一个新容器的时候,Docker从可用的地址段中选择一个空闲的ip地址分配给容器的eth0端口。使用本地主机上docker0接口的IP作为所有容器的默认网关。

sudo docker run -i -t --rm base /bin/bash
$ ip addr show eth0
24: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 32:6f:e0:35:57:91 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::306f:e0ff:fe35:5791/64 scope link
       valid_lft forever preferred_lft forever
$ ip route
default via 172.17.42.1 dev eth0
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.3

4.6 自定义网桥

除了默认的docker0网桥,用户也可以指定网桥来连接各个容器。

  在启动Docker服务的时候,使用-b BRIDGE--bridge=BRIDGE来指定使用的网桥。
  如果服务已经运行,那需要先停止服务,并删除旧的网桥

sudo systemctl stop docker
sudo ip link set dev docker0 down
sudo brctl delbr docker0

然后创建一个网桥bridge0

sudo brctl addbr bridge0
sudo ip addr add 192.168.5.1/24 dev bridge0
sudo ip link set dev bridge0 up

查看确认网桥创建并启动

$ ip addr show bridge0
4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default
    link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.1/24 scope global bridge0
       valid_lft forever preferred_lft forever

在Docker配置文件/etc/docker/daemon.json中添加如下内容,即可将Docker默认桥接到创建的网桥上

{
    "bridge": "bridge0"
}

此时启动docker服务,再新建容器,可以看到它已经桥接到了bridge0

4.7 编辑网络配置文件

Docker 1.2.0开始支持再运行中的容器里编辑/etc/hosts/etc/hostname/etc/resolv.conf文件。但是这些修改都只是临时的,只在运行中的容器里保留,容器终止或重启后并不会被保存下来,也不会被docker commit提交。

4.8 配置HTTP/HTTPS网络代理

为dockerd设置网络代理

docker pull命令是由dockerd守护进程执行。而dockerd守护进程是由systemd管理。如果想在使用docker pull命令时使用HTTP/HTTPS代理,需要在systemd中进行配置

为dockerd创建配置文件夹
sudo mkdir -p /etc/systemd/system/docker.service.d
为dockerd创建HTTP/HTTPS网络代理的配置文件,文件路径是:/etc/systemd/system/docker.service.d/http-proxy.conf。并在文件中添加相关环境变量
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080/"
Environment="HTTPS_PROXY=http://proxy.example.com:8080/"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
刷新配置并重启docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
为docker容器设置网络代理

在容器运行阶段,如果需要使用HTTP/HTTPS网络代理,可以通过更改docker客户端配置,或者指定环境变量的方式

更改docker客户端配置

创建或更改~/.docker/config.json,并在该文件中添加相关配置。

{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://proxy.example.com:8080/",
     "httpsProxy": "http://proxy.example.com:8080/",
     "noProxy": "localhost,127.0.0.1,.example.com"
   }
 }
}
指定环境变量
环境变量docker run示例
HTTP_PROXY–env HTTP_PROXY=“http://proxy.example.com:8080/”
HTTPS_PROXY–env HTTPS_PROXY=“http://proxy.example.com:8080/”
NO_PROXY–env NO_PROXY=“localhost,127.0.0.1,.example.com”
为docker build过程设置网络代理

在容器构建阶段,如果需要使用HTTP/HTTPS代理,可以通过指定docker build的环境变量,或者在Dockerfile中指定环境变量的方式

使用-build-arg指定环境变量
docker build \
    --build-arg "HTTP_PROXY=http://proxy.example.com:8080/" \
    --build-arg "HTTPS_PROXY=http://proxy.example.com:8080/" \
    --build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" .
在Dockerfile中指定相关环境变量
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值