一、网络启动与配置参数

Docker启动时会在主机上自动创建一个docker0虚拟网桥实际上是一个Linux网桥
可以理解为一个软件交换机它会在挂载其上的接口之间进行数据转发
同时,Docker随机分配一个本地未占用的私有网段(在RFC1918中定义)中的一个地址给docker0接口

当创建一个Docker容器时,同时会创建一对veth pair接口
当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包
这对接口一端在容器内,即eth0,另一端在本地并被挂载到docker0网桥
名称以veth开头,通过这种方式,主机可以跟容器通讯,容器之间也可以相互通信。
如此一来,Docker就创建了在主机和所有容器之间的一个虚拟共享网络。

下面是Docker网络相关的参数命令,其中有些命令选项只有在Docker服务启动的时候才能配置,而且不能马上生效。
  -b BRIDGE or --bridge=BRIDGE  指定容器挂载的网桥
  --bip=CIDR  定制docker0的掩码
  -H SOCKET ... or --host=SOCKET...  docker服务端接收命令的通道
  --icc=true|false  是否支持容器之间进行通信
  --ip-forward=true|false  启用net.ipv4.ip_forward
  --iptables=true|false  禁止Docker添加iptables规则
  --mtu=BYTRS  容器网络中的MTU

下面两个命令既可以在启动服务时指定,也可以Docker容器启动时(docker run)指定。
在docker服务启动的时候指定则会成为默认值,后续执行docker run时可以覆盖设置的默认值。
  --dns=IP_ADDRESS  使用指定的DNS服务器
  --dns=search=DOMAIN  指定DNS搜索域

最后这些选项只能在docker run执行时使用,因为他是针对容器的特性内容:
  -h HOSTNAME or --hostname=HOSTNAME  配置容器主机名
  --link=CONTAINER_NAME:ALIAS  添加到另一个容器的连接
  --net=bridge|none|container:NAME_or_ID|host|user_defined_network  配置容器的桥接模式
  -p SPEC or --publish=SPEC  映射容器端口到宿主主机
  -P or --publish-all=true|false  映射容器所有端口到宿主主机

其中 --net选项支持五种模式,如下所示:
  --net=bridge 默认选项,为容器创建一个独立的网络命名空间,分配网卡、ip地址等网络配置。
    并通过veth接口对将容器挂载到一个虚拟网桥(默认为docker0)上。
  --net=none 为容器创建一个独立的网络命名空间,但不进行网络配置,即容器内没有创建网卡、IP等
  --net=container:NAME_or_ID 意味着新创建的容器共享指定的已存在容器的网络命名空间,
    两个容器内的网络配置共享,但其它资源(进程空间、文件系统等)还是隔离的。
  --net=host 意味着不为容器创建独立的网络命名空间,容器内看到的网络配置均与主机保持一致。
  --net=user_defined_network 用户自行用network相关命令创建一个网络,
    同一个网络内的容器彼此可见,可以采用更多类型的网络插件。

二、配置容器DNC和主机名

Docker支持自定义容器的主机名和DNS配置。

1.相关配置文件

实际上,容器中主机名和DNS配置信息都是通过三个系统配置文件来维护的:/etc/resolv.conf/etc/hostname/etc/hosts

启动一个容器,在容器中使用mount命令可以看到这三个文件的挂载信息。

其中,/etc/resolv.conf文件在创建容器的时候,默认会与宿主机/etc/resolv.conf文件内容保持一致。

这样也可以说明容器和宿主的文件系统是共享的。

/etc/hosts文件默认中只记录容器自身的一些地址和名称。

2.容器内修改配置文件

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

3.通过参数指定

如果用户想要自定义容器的配置,可以在创建或启动容器的时候利用下面的参数指定。

  指定主机名

    -h HOSTNAME或--hostname=HOSTNAME。设定容器的主机名,它会被写到容器内的/etc/hosts和/etc/hostname文件中。
    但是这个主机名只有在容器内才能看到,在容器外看不到,既不会在docker ps中显示,也不会在其它容器的/etc/hosts中看到。

  记录其它容器主机名

    --link=CONTAINER_NAME:ALLAS。在创建容器的时候,添加一个所连接容器的主机名到容器内/etc/hosts文件中。
    这样新创建容器可以直接使用主机名来与所连接容器通信。

  指定DNS服务器

    --dns=IP_ADDRESS。添加DNS服务器到容器的/etc/resolv.con中,
    容器会用指定的服务器来解析所有不在/etc/hosts中的主机名。

  指定DNS搜索域

    --dns-search=DOMAIN。设定容器的搜索域,当设定搜索域为.example.com时,在搜索一个名为host的主机时,
    DNS不仅搜索host,还会搜索host.example.com。

三、容器访问控制

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

1.容器访问外部网络

容器默认指定了网关为docker0网桥上的docker0内部接口。
docker0内部接口也是宿主机的一个本地接口,因此默认情况下是可以访问到宿主机本地的。

容器想要通过宿主机访问到外部网络,需要宿主机进行转发。
在Linux系统中,检查转发是否打开(默认是打开的):

如果为0,说明没有开启转发,则需要手动打开:

更简单的,在启动Docker服务的时候设定--ip-forward=true,docker服务会自动打开宿主机系统的转发服务。

2.容器之间的访问

容器之间相互访问,需要两方面的支持:
  网络拓朴是否已经连通。默认情况下,所有容器都会连接到docker0网桥上,这意味着默认情况下拓扑是互通的;
  本地系统的防火墙软件iptables是否允许访问通过。这取决于防火墙的默认规则是允许还是禁止。
下面分两种情况介绍容器之间的访问。

(1)访问所有端口

当启动Docker服务的时候,默认会添加一条“允许”转发策略到iptables的FORWARD链上。
通过配置--icc=true|false(默认为true)参数可以控制默认的策略。
为了安全考虑,可以在Docker配置文件中配置DOCKER_OPTS=--icc=false来默认禁止容器之间的相互访问。
同时,如果启动Docker服务时手动指定--iptables=false参数则不会修改宿主机系统上的iptables规则。

(2)访问指定端口

在通过-icc=false禁止容器间相互访问后,仍可以通过--link=CONTAINER_NAME:ALIAS选项来允许访问指定容器的开放端口。
--link=CONTAINER_NAME:ALIAS中的CONTAINER_NAME必须是docker自动分配的主机名或使用--name指定的主机名,不能使用-h参数配置的主机名。

四、映射容器端口到宿主机的实现

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

1.容器访问外部实现

假设容器内部的网络地址为172.12.0.2,本地网络地址为10.0.2.2。
容器要能访问外部网络,源地址不能为172.12.0.2,需要进行源地址映射(Source NAT,SNAT),
修改为本地系统的IP地址10.0.2.2。
映射是通过iptables的源地址伪装操作实现的。

查看主机nat表上POSTROUTING链的规则。该链负责网包离开主机之前,还写其源地址。

其中,上述规则将所有源地址为172.12.0.0/16网段,而不是从docker0接口发出的流量,动态伪装为系统网卡发出。
MASQUERADE行动跟传统SNAT行动相比,好处是它能从网卡动态获取地址。

2.外部访问容器实现

容器允许外部访问,可以在docker run时候通过-p或-P参数来启用。
不管用那种方法,其实也是在本地的iptable的nat表中添加相应的规则,
将访问外部IP地址的网包进行目标地址DANT,将目标地址修改为容器的IP地址
以一个开放的8080端口为例,使用-P会自动映射本地的一个随即端口到容器的8080端口。

可以看到,nat中涉及两条链,PREROUTING链负责包到达网络接口时,改写其目标地址。
其中规则将所有流量都仍到DOCKER链。而DOCKER链中所有不是从docker0进来的网包(意味着不是本地主机产生),
将目标端口为49153的,修改目标地址为172.17.0.11,目标端口修改为80。

需要注意的是,这里的而规则映射了0.0.0.0,意味着将接收主机来自所有网络接口上的流量。
可以通过-p IP:host_port:container_port或-p IP::port来指定绑定的外部网络接口,以制定更严格的访问规则。
如果希望映射永久绑定到某个固定的IP地址,可以在docker配置文件/etc/default/docker中指定DOCKER_OPTS="--ip=IP_ADDRESS",之后重启Docker服务即可生效。

五、配置docker0网桥

Docker服务默认会创建一个名称为docker0的Linux网桥,它在内核层连通了其它的物理或虚拟网卡。
这就将所有容器和本地主机都放到了同一个物理网络。用户使用Docker创建多个自定义网络时可能会出现多个容器网桥。

Docker默认制定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
它还给出了MTU(接口允许接收的最大传输单元),通常是1500字节,或宿主网络路由上支持的默认值。
这些值都可以在服务启动的时候进行配置:
  --bip=CIDR:IP地址加掩码格式,例如192.168.1.5/24
  --mtu=BYTES:覆盖默认的Docker mtu配置。

也可以在配置文件中配置DOCKER_OPTS,然后重启服务。
由于目前Docker网桥是Linux网桥,用户可以使用brctl show来查看网桥和端口连接信息。

每次创建一个新的容器时,Docker从可用的地址段中选择一个空闲的IP地址来分配给容器的eth0端口。
并且使用本地主机上docker0接口的IP作为容器的默认网关:

六、自定义网桥

除了默认使用docker0网桥,用户也可以指定网桥来连接各个容器。
在启动docker服务的时候,使用-b BRIDGE或--bridge=BRIDGE来指定使用的网桥。
停止服务:
  service docker stop
关闭docker网桥:
  ip link set dev docker0 down
删除旧的网桥:
  brctl delbr docker0
新建网桥:
  brctl addbr bridge0
给新的网桥配置参数:
  ip addr add 192.168.5.1/24 dev bridge0
  ip link set dev bridge0 up
  ip addr show bridge0

这是传统的方法,现在直接使用docker create network。

七、使用OpenvSwitch网桥

Docker默认使用的是Linux自带的网桥实现,实际上,OpenvSwitch项目作为一个成熟的虚拟交换机,具备更丰富的功能。

1.安装OpenvSwitch

安装依赖包:
  yum -y install openssl-devel wget kernel-devel
安装开发工具:
  yum groupinstall "Development Tools"
下载源码:
  wget http://openvswitch.org/releases/openvswitch-2.3.1.tar.gz
解压:
  tar xfz openvswitch-2.3.1.tar.gz
创建编译目录:
  mkdir -p ~/rpmbuild/SOURCES
从spec文件中删除openvswitch-kmod的依赖包,并创建一个新的spec文件:
  sed 's/openvswitch-kmod, //g' openvswitch-2.3.1/rhel/openvswitch.spec > openvswitch-2.3.1/rhel/openvswitch_no_kmod.spec
开始编译:
  cp openvswitch-2.3.1.tar.gz rpmbuild/SOURCES
  rpmbuild -bb --without=check ~/openvswitch-2.3.1/rhel/openvswitch_no_kmod.spec
安装编译生成的rpm文件:
  yum localinstall /home/ovswitch/rpmbuild/RPMS/x86_64/openvswitch-2.3.1-1.x86_64.rpm

启动服务:systemctl start openvswitch.service
查看服务状态:systemctl -l status openvswitch.service

2.配置容器连接到OpenvSwitch

目前OpenvSwitch网桥还不能直接支持挂载容器,需要手动在OpenSwitch网桥上创建虚拟网口被挂载到容器中。
步骤如下:

(1)创建无网络容器   

  docker run --net=noen --privileged=true -it base /bin/bash
查看网络信息:

只有一个本地网卡lo

(2)手动为容器添加网络

下载辅助脚本ovs-docker:
  wget https://github.com/openvswitch/ovs/raw/master/utilities/ovs-docker
  chmod a+x ovs-docker
添加网桥br1,并挂载:
  ovs-vsctl add-br br1
  ovs-vsctl show(查看)

./ovs-docker add-port br1 eth0 c26f1bbdb3f5 --ipaddress=172.17.0.2/24
可以看到容器内多了一个网卡:

在容器外,为br1配置接口地址。
  ifconfig br1 172.17.0.10/24

八、创建一个点到点的连接

默认情况下,Docker会将所有容器连接由docker0提供的虚拟子网中,
有时候需要两个容器之间可以直接通讯,而不同通过主机网桥进行桥接。

创建一对peer接口,分别放到两个容器中,配置成点到点链路类型即可。

启动两个容器:
  docker run -it --rm --net=none centos /bin/bash

找到进程号,然后创建网络命名空间的跟踪文件:

  1. docker inspect -f "{{.State.Pid}}" d3e573778246
  2. docker inspect -f "{{.State.Pid}}" 3882bde4d974
  3. mkdir -p /var/run/netns
  4. ln -s /proc/25974/ns/net /var/run/netns/25974
  5. ln -s /proc/26023/ns/net /var/run/netns/26023
  6. ip link add AA type veth peer name BB

添加IP地址和路由信息:

  1. ip link set AA netns 25974
  2. ip netns exec 25974 ip addr add 10.1.1.1/32 dev AA
  3. ip netns exec 25974 ip link set AA up
  4. ip netns exec 25974 ip route add 10.1.1.2/32 dev AA
  5.  
  6. ip link set BB netns 26023
  7. ip netns exec 26023 ip addr add 10.1.1.2/32 dev BB
  8. ip netns exec 26023 ip link set BB up
  9. ip netns exec 26023 ip route add 10.1.1.1/32 dev BB

ping:

此外也可以不指定--net=none来创建点链路。

docker——网络配置的更多相关文章

  1. docker网络配置

    Docker网络配置 Docker网络模式介绍 Docker在创建容器时有四种网络模式:bridge/host/container/none,bridge为默认不需要用--net去指定,其他三种模式需 ...

  2. Docker网络配置、Docker部署分布式项目

    目标 1.Docker网络配置 2.Docker部署SpringCloud项目 Docker网络配置 Docker网络模式介绍 Docker在创建容器时有四种网络模式:bridge/host/cont ...

  3. docker网络配置方法总结

    docker启动时,会在宿主主机上创建一个名为docker0的虚拟网络接口,默认选择172.17.42.1/16,一个16位的子网掩码给容器提供了65534个IP地址.docker0只是一个在绑定到这 ...

  4. Docker(六):Docker网络配置进阶

    1.Docker集群网络配置之Weave Weave是Github上一个比较热门的Docker容器网络方案,具有非常良好的易用性且功能强大.仓库地址:https://github.com/weavew ...

  5. 5、Docker网络配置(单机)

    一.概述 以下内容参考:https://docs.docker.com/network/#network-drivers Docker容器和服务如此强大的原因之一是您可以将它们连接在一起,或者将它们连 ...

  6. Docker网络配置进阶

    Docker启动会默认创建docker0虚拟网桥,是Linux的一个bridge,可以理解成一个软件交换机.它会在挂载到它的网口之间进行转发. 之后所有容器都是在172.17.0.x的网段上,并且可以 ...

  7. docker网络配置之自定义网桥

    使用特定范围的 IP (仅适用于v1.x)不适用于新版的v1.1x Docker 会尝试寻找没有被主机使用的 ip 段,尽管它适用于大多数情况下,但是它不是万能的,有时候我们还是需要对 ip 进一步规 ...

  8. docker 网络配置

    先随便写几行命令 随后一点点的补充 端口映射实现访问容器. run -d -P training/webapp python app.py run -d -p 5000:5000 training/w ...

  9. Docker网络配置概述

    Overview One of the reasons Docker containers and services are so powerful is that you can connect t ...

随机推荐

  1. visual studio 2017使用NHibernate4.0连接oracle11g数据库

    之前一直是公司用NHibernate2.1来做项目,连接oracle 10g的数据库,配置NHibernate的东西都是以前的同事做好了的,也怪自己太懒了,没尝试过配置这个东西,虽然一直在使用NHib ...

  2. oracle 触发器 pragma autonomous_transaction

    from:http://blog.csdn.net/ruru7989/article/details/30712987一般情况下在触发器中是不能使用DDL语句的,使用自治事务可以实现 可以在触发器中加 ...

  3. ios 6以后,UILabel全属性

    一.初始化 1 UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 40, 120, 44)]; 2       3 [s ...

  4. pl/sql编程2-综合

    案例1,要求:可以向book表添加书,并通过Java程序调用该过程1.1 创建表 ),publishHosuse )); 1.2 编写过程,无返回值 create or replace procedu ...

  5. date类型数据插入

    --字段类型是dateinsert into tab(column) values(to_date('2017_06_30 11:38:22','yyyy-mm-dd hh24:mi:ss'));-- ...

  6. 关于MCU的烧录,下载与其他接口的比较(一)

    今天呢,犯了一个很严重的错误,我不知道这会产生什么样的影响,但我知道,如果我以后再没有具体的了解,仔细认真地观察,认证,只会滑到无底的深渊.做技术来不得半点虚假,切记一知半解,凡事都要弄得清楚明白,认 ...

  7. iOS-利用插件实时刷新模拟器(提高效率)

    解决办法: 1.需要给Xcode安装一个Alcatraz插件 安装完成后:点击window 下面的 package manager 安装我们今天的主角 2. ‘Injection Plugin for ...

  8. JS Date parse

    因为JS中的Date转换格式没有“-”这种间隔符,Date.parse会生成NAN,所以只能进行转换. <script type="text/javascript"> ...

  9. 解决 ssh 登录到ubuntu server 慢的问题

    最近在服务器上使用ubuntu系统,服务器上开启sshd服务,在客户端处使用ssh登录到服务器的时候出现卡顿的现象. 在网上搜索了解决方案,主要是: 1. 修改服务器的 /etc/ssh/sshd_c ...

  10. Microchip编译器产品线—MPLAB XC简介

    以下为Microchip最新编译器产品线—MPLAB-XC简介 MPLAB-XC:适合所有PIC单片机和项目的编译器解决方案 Microchip最新编译器产品线—MPLAB-XC为项目开发的软件需求提 ...