Skip to content

docker网络

docker网络

目录

[toc]

docker网络

1、docker网络模型

bash
 veth pair:成对出现的一种虚拟网络设备,数据从一端进,从另一端出。 用于解决网络命名空间之间隔离。(相当于一根网线)
 docker0:网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。
引入网桥(docker0)的作用:
1.解决容器之间的通信(2层之间的通信)
2.解决宿主机和容器命名空间隔离问题;

2、Docker使用iptables实现网络通信

bash
Docker使用iptables实现网络通信。

外部访问容器:
# iptables -t nat -vnL DOCKER

容器访问外部:
# iptables -t nat -vnL POSTROUTING

#注意:这里的虚线代表一个隔离的网络命名空间!

3、实例测试

我们先来创建一个容器:

bash
[root@docker ~]# docker run -d --name nginx -p 88:80 nginx
994c016655ef16ee64adf748c17e6256c1ed31c2237dabdc2b1d8fc8c57549ee
[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS                               NAMES
994c016655ef   nginx     "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:88->80/tcp, :::88->80/tcp   nginx
[root@docker ~]#

现在在笔记本浏览器上输入http://172.29.9.32:88/可以测试下:

或者在宿主机命令行用curl命令测试下即可:

bash
[root@docker ~]# curl 172.29.9.32:88
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@docker ~]#

我们再来看看容器映端口的映射情况:

bash
[root@docker ~]# ss -antlp|grep 88
LISTEN     0      1024         *:88                       *:*                   users:(("docker-proxy",pid=20252,fd=4))
LISTEN     0      1024      [::]:88                    [::]:*                   users:(("docker-proxy",pid=20257,fd=4))
[root@docker ~]#

查看下当前系统下的网卡ip情况:

bash
[root@docker ~]# ifconfig 
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:c5ff:fe1c:5bd3  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c5:1c:5b:d3  txqueuelen 0  (Ethernet)
        RX packets 117  bytes 16377 (15.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 161  bytes 15411 (15.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.29.9.32  netmask 255.255.0.0  broadcast 172.29.255.255
        inet6 fe80::20c:29ff:fe56:3f5  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:56:03:f5  txqueuelen 1000  (Ethernet)
        RX packets 6828  bytes 3659631 (3.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3599  bytes 583426 (569.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 24343  bytes 42494064 (40.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 24343  bytes 42494064 (40.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth8a8c209: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::5cb6:bdff:fe47:be9e  prefixlen 64  scopeid 0x20<link>
        ether 5e:b6:bd:47:be:9e  txqueuelen 0  (Ethernet)
        RX packets 19  bytes 3534 (3.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 31  bytes 2877 (2.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@docker ~]#

(1)我们看下外部网络访问容器

bash
[root@docker ~]# iptables -t nat -vnL DOCKER

走的是路由表:

bash
[root@docker ~]# ip route
default via 172.29.0.254 dev ens33 
169.254.0.0/16 dev ens33 scope link metric 1002 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.29.0.0/16 dev ens33 proto kernel scope link src 172.29.9.32

docker0又是一个二层的网桥设备,它会基于arp发送广播,然后与相应的容器进行通信。

(2)那么容器与外部网络如何进行通信呢?

创建并进入容器,进行ping测试:

bash
[root@docker ~]# docker run -it --name=test --rm busybox:1.28.3 
#我们ping百度进行测试
/ # ping baidu.com
PING baidu.com (220.181.38.148): 56 data bytes
64 bytes from 220.181.38.148: seq=0 ttl=127 time=32.968 ms
64 bytes from 220.181.38.148: seq=1 ttl=127 time=30.789 ms
^C
--- baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 30.789/31.878/32.968 ms
/ # 
#看下自己容器当前eth0的ip是172.17.0.2
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:14 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1149 (1.1 KiB)  TX bytes:418 (418.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 
#在看下当前容器的路由表:
/ # ip route 
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.2

再看下宿主机的路由表:

bash
[root@docker ~]# ip route
default via 172.29.0.254 dev ens33 #走的是默认路由
169.254.0.0/16 dev ens33 scope link metric 1002 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.29.0.0/16 dev ens33 proto kernel scope link src 172.29.9.32 

[root@docker ~]# ifconfig 
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:c5ff:fe1c:5bd3  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c5:1c:5b:d3  txqueuelen 0  (Ethernet)
        RX packets 123  bytes 16711 (16.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 167  bytes 15904 (15.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.29.9.32  netmask 255.255.0.0  broadcast 172.29.255.255
        inet6 fe80::20c:29ff:fe56:3f5  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:56:03:f5  txqueuelen 1000  (Ethernet)
        RX packets 10211  bytes 4864742 (4.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5719  bytes 847549 (827.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 34888  bytes 60503678 (57.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 34888  bytes 60503678 (57.7 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@docker ~]#

注意下:这里的docker0--eth0有做一次的SNAT转换

bash
[root@docker ~]# iptables -t nat -vnL POSTROUTING 
Chain POSTROUTING (policy ACCEPT 372 packets, 23096 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    3   194 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
[root@docker ~]#

测试结束。

4、不同宿主机之间, docker容器网络通信有几种方式?

容器跨宿主机容器通信问题。

这是一种需求;

数据包封装实现︰overlay(隧道方案)和路由方案

技术∶flannel、weave、calico

实战-docker配置静态ip(已成功测试-已博客输出-mk老师)-20210525

实验涉及软件百度云链接

bash
链接:https://pan.baidu.com/s/1ScjBiN3Q27wsHu1VLwGXYw 
提取码:3q06

实验环境

一个还原到之前安装了 docker 的虚拟机快照:centos7.7 1908虚机。如何在centos7上安装docker环境,可以在我的博客查找文章:3-实战-centos上安装docker-(过程超详细-已测试成功)-20210522

前言

(1)Docker 的 4 种网络模式

Docker有以下4种网络模式︰

host模式,使用--net=host指定。

container模式,使用--net=container:NAME_or_ID指定。

none模式,使用--net=none指定。

bridge模式,使用--net=bridge指定,默认就是bridge模式

默认选择bridge的情况下,容器启动后会通过DHCP 获取一个地址,这可能不是我们想要的,在centos7系统上,docker环境下可以使用**pipework脚本(官方提供的脚本)**对容器分配固定IP(这个IP可以是和物理机同网段IP)

注: docker 默认是bridge ( --net=bridge )模式,相当于VMware 中NAT模式。docker环境下可以使用pipework脚本对容器分配固定IP,相当于VMware中桥接模式。注:Pipework有个缺陷,容器重启后IP设置会自动消失,需要重新设置

扩展∶--privileged=true  #允许开启特权功能

privileged ['prrvalrdgd]有特权的

在docker 0.6版以后,privileged 被引入docker。使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部物理机的一个普通用户权限。使用privileged启动的容器,可以看到很多host上的设备,并且可以执行mount甚至允许你在docker容器中启动docker容器。不启用privileged,容器中root用户不能执行mount。

(2)扩展:测试 privileged 特权功能

1、未设置 privileged 特权的容器:

bash
[root@docker ~]# docker run -it centos bash
[root@80a9f7e36df2 /]# ls /dev/ #可以看到的设备文件比较少
console  core  fd  full  mqueue  null  ptmx  pts  random  shm  stderr  stdin  stdout  tty  urandom  zero
[root@80a9f7e36df2 /]# mount /dev/sda1 /opt/ #不可以挂载成功, 
mount 命令执行失败mount: /opt: permission denied.
[root@80a9f7e36df2 /]# mount -o bind /etc/ 
/optmount: /opt: permission denied.
[root@80a9f7e36df2 /]# exit

2、使用 privileged 特权的容器

bash
[root@docker ~]# docker run -it --privileged centos bash
[root@fac986b64e15 /]# ls /dev/ #可以看到很多设备文件
[root@fac986b64e15 /]# mount /dev/sda1 /opt/ #可以挂载物理机上的 sda1 分区
[root@fac986b64e15 /]# umount  /opt
[root@fac986b64e15 /]# mount -o bind /etc/ /opt #可以挂载成功
[root@fac986b64e15 /]# umount  /opt/
[root@fac986b64e15 /]# exit
exit
[root@docker ~]#
[root@docker ~]# docker run -it --privileged centos bash
[root@906b0421babd /]# init 0 #不能使用 init 0 关机,还是使用 exit 退出 
dockerCouldn't find an alternative telinit implementation to spawn.

0、基础环境配置

一个还原到之前安装了 docker 的虚拟机快照:centos7.7 1908虚机。如何在centos7上安装docker环境,可以在我的博客查找文章。

1、配置桥接网络

桥接本地物理网络的目的,是为了局域网内用户方便访问docker实例中服务,不要需要各种端口映射即可访问服务。但是这样做又违背了docker 容器的安全隔离的原则,工作中辩证的选择。

  • 创建桥设备 br0:

安装包:

bash
[root@docker ~]# yum install -y bridge-utils
  • 把 ens33 绑到 br0 桥设备上:

配置前网卡配置如下:

bash
#开始配置
[root@docker ~]# cd /etc/sysconfig/network-scripts/
[root@docker network-scripts]# cp ifcfg-ens33 /opt/ #备份ifcfg-ens33
[root@docker network-scripts]# vim ifcfg-ens33 #编辑配置文件为以下内容
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
#UUID=3bff16f1-d739-485c-9e02-197c4678f51c
DEVICE=ens33
ONBOOT=yes
BRIDGE="br0"

  • 生成桥设备 br0 的配置文件:
bash
[root@docker network-scripts]# vim ifcfg-br0 #创建 ifcfg-br0 文件,并写入以下内容
DEVICE="br0"
NM_CONTROLLED="yes" 
ONBOOT="yes"
TYPE="Bridge"
BOOTPROTO=none
IPADDR=172.29.9.11
NETMASK=255.255.0.0
GATEWAY=172.29.0.254
DNS1=114.114.114.114

注:TYPE="Bridge"
  • 重启网络并测试,
bash
[root@docker ~]# systemctl restart network

配置桥接网络后,查看ip:

2、使用 pipework 脚本配置静态 IP

方法 1:直接下载 pipework zip 包

https://github.com/jpetazzo/pipework

方法 2:使用 git 获得:

git 下载链接:https://github.com/jpetazzo/pipework.git

bash
git clone https://github.com/jpetazzo/pipework.git
  • 本次使用方法直接把压缩包上传到Linux机器上
bash
[root@docker ~]# unzip pipework-master.zip  # 不需要编译,因为 pipework 是一个shell 脚本
[root@docker ~]# cd pipework-master
#[root@docker pipework-master]# vim pipework #查看pipework脚本内容,480几行的内容
[root@docker pipework-master]# cp pipework /usr/bin/ #方便后期使用 pipework 命令

到此 pipework 已经安装成功。

启动docker:

bash
[root@docker ~]# systemctl start docker

拉取一个centos镜像:

bash
docker pull centos

3、使用静态 IP 启动一个 docker 实例

例:以none模式,使用--net=none启动一个容器,并且开启docker 特权模式。

bash
[root@docker ~]# docker run -itd --net=none --privileged=true centos bashe5ca1cc49de1db462ebf405a5735a2dc1ee43f28b2887bd00559c2ae22b4b505
[root@docker ~]#
  • 扩展结束,接着给容器配置表态 IP 地址
bash
[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMESe5ca1cc49de1   centos    "bash"    12 minutes ago   Up 12 minutes             
trusting_rosalind
[root@docker ~]#可以看到容器启动的 ID ,比如是e5ca1cc49de1

给此容器配置地址:

pipework语法:pipework 网桥名 容器实例ID 分配给容器的IP/掩码@网关

bash
[root@docker ~]# pipework br0 e5ca1cc49de1 172.29.9.21/16@172.29.0.254 #注:容器的 DNS 地址,会直接使用物理机的 dns

注意用pipwork脚本配置ip后,不需要重启网络,容器ip马上就会生效的。

  • 测试 IP:#可以看到 docker 实例的 IP 已经可以使用

bash
[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMESe5ca1cc49de1   centos    "bash"    16 minutes ago   Up 16 minutes             trusting_rosalind[root@docker ~]# docker inspect e5ca1cc49de1 #查看容器的详细情况

  • 进入入容器,测试网络:
bash
[root@docker ~]# docker ps
[root@docker ~]# docker exec -it e5ca1cc49de1 bash #进入容器
[root@e5ca1cc49de1 /]# yum install -y net-tools #安装ifconfig命令
[root@e5ca1cc49de1 /]# cat /etc/resolv.conf 
[root@e5ca1cc49de1 /]# ifconfig
[root@e5ca1cc49de1 /]# route -n

到此,docker 实例配置静态 IP 成功。

4、小案例: 使用静态 IP 启动的 docker 实例运行,一个 web 服务器

bash
[root@c8f88d9bf76e /]# yum install -y httpd
[root@c8f88d9bf76e /]# systemctl start httpd
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
[root@c8f88d9bf76e /]#
[root@c8f88d9bf76e /]# /usr/sbin/httpd -DFOREGROUND &
[root@c8f88d9bf76e /]# netstat -antup|grep 80
[root@c8f88d9bf76e /]# cd /var/www/html/
[root@c8f88d9bf76e html]# ls
[root@c8f88d9bf76e html]# echo  Linux-k8s > index.html

5、总结

关于如何给docker配置静态ip,配置步骤总结如下:

1、创建一个 br0 桥接设备

2、下载 pipework 包并安装

3、安装并运行 docker

4、拉取一个 centos docker 镜像

5、启动一个 docker 实例 注意加参数: --net=none --privileged=true

6、使用 pipework 给 docker 实例配置 IP

7、小案例:使用静态 IP 启动的 docker 实例运行,一个 web 服务器

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 微信二维码

x2675263825 (舍得), qq:2675263825。

🍀 微信公众号

《云原生架构师实战》

🍀 csdn

https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

🍀 博客

www.onlyyou520.com

🍀 知乎

https://www.zhihu.com/people/foryouone

🍀 语雀

https://www.yuque.com/books/share/34a34d43-b80d-47f7-972e-24a888a8fc5e?# 《云笔记最佳实践》

最后

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

最近更新