Docker 学习 | 第六篇:容器网络配置

前言

Docker容器中可以运行网络应用,可以让外部可以访问容器。Docker提供了很多对网络的配置命令。本篇文章主要介绍Docker中的网络默认配置/网络端口映射/容器互联/DNS配置/网络模型等等网络相关的知识。

Docker默认的网络配置

Docker启动的时候会在主机上自动创建一个docker0网桥,实际上是一个Linux网桥,所有容器的启动如果在docker run的时候没有指定网络模式的情况下都会挂载到docker0网桥上。这样容器就可以和主机甚至是其他容器之间通讯了。

我们可以通过以下命令查看Docker0网桥:

[root@VM_0_14_centos ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242f9dd21f4       no              veth211edda

如果想查看Docker0IP地址可以通过ifconfig命令

[root@VM_0_14_centos ~]# 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
        ether 02:42:f9:dd:21:f4  txqueuelen 0  (Ethernet)
        RX packets 838  bytes 114894 (112.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1225  bytes 568128 (554.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

如果发现找不到brctl命令,可以同过yum install -y brctl安装

外部访问容器

在使用docker run的时候可以使用-P或者-p来进行容器和主机之间的端口映射。

使用-P则不需要指定任何映射关系,默认情况下,Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口。

使用-p则需要指定对应的主机的端口应该到容器中的端口。使用格式如下:

-p hostPort:containerPort 

不管使用哪一种方式进行端口映射,其他原理都是在本地的iptablenat表中添加相应的规则,将访问外部IP地址的网包进行目标地址的转换,将目标地址修改为容器的IP地址。可以通过以下命令来查看iptablenat表:

[root@VM_0_14_centos ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
607df94722dd        redis               "docker-entrypoint.s…"   9 days ago          Up 3 days           0.0.0.0:62255->6379/tcp   redis
[root@VM_0_14_centos ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 239K packets, 7950K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 239K 7979K DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 239K packets, 7950K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 267K packets, 18M bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 267K packets, 18M bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2           tcp dpt:6379

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0           
  481 28828 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:62255 to:172.17.0.2:6379
[root@VM_0_14_centos ~]#

从上面可以看到,Docker中跑了一个容器名为redis,并且把本机的62255端口映射到了容器的6379端口上。
通过查看nat表,可以看到,有两条链。POSTRONTING的第二个规则负责包到达网络接口时,改写其目的地址,将所有的流量都扔到DOCKER链,而DOCKER链的第二个规则将所有不是从docker0进入的网包,将目标端口为62255的,都修改目标地址为172.17.0.2,端口为6379

由于本篇不是介绍iptable的,并且可能笔者对于iptable理解的不够深入,上述说法仅仅是表达的笔者的理解,可能有些说法存在错误。~

容器访问外部网络

默认情况下,容器可以访问到外部网络的连接,因为容器的默认网络接口为docker0网桥上的接口,也即是主机上的本地接口。其原理是通过Linux系统的转发功能实现的,在Linux中检查转发是否打开:

[root@VM_0_14_centos ~]# sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

0表示转发未打开,1表示转发已经打开。可以在docker run时使用--ip-forward=true来指定,Docker会打开主机的转发功能。

同时可以通过上述的nat表中找到对应的规则,在POSTRONTING的第一个规则就是把所有原地址在172.17.0.0/16网段但不是属于Docker0的网包(即容器中的网包),动态伪装为0.0.0.0/0网段,即主机网卡。

配置容器DNS和主机名

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

  • /etc/resolv/conf在创建容器的时候,会默认与本地主机/etc/resolv.conf保持一致
  • /etc/hosts中则记载了容器自身的一些地址和名称。
  • /etc/hostname中记录的容器的主机名

可以直接在容器内部修改这三个文件使之直接生效,不过这些修改只会在容器中保留,容器重启后则又会恢复原样,同样的,docker commit也无法保存这三个文件的修改。

配置主机名

配置主机名可以通过docker run的时候使用-h hostname或者--hostname hostname这样的形式来执行。

配置DNS

可以统一配置所有容器的DNS,通过修改主机/etc/docker/daemon.json增加以下内容:

{
    "dns" : [
        "114.114.114.114",
        "8.8.8.8"
    ]
}

同时,也可以通过在docker run的时候使用--dns=address参数来指定.

容器互联

容器之间相互通讯可以通过docker run中的--link=container_name:alias参数来达到效果。
此种方式可以很方便让容器使用容器名进行通讯,而不需要依赖ip地址,不过link方式仅仅解决了单机容器间的互联,多机的情况下,需要通过别的方式进行连接。

自定义网络方式

除了使用link方式,还可以使用自定义网桥的方式进行互联。

下面演示了通过自定义网络方式来使容器互联

[root@VM_0_14_centos ~]# docker network create -d bridge my-net
d90fc3d8515b9402f2aca86767aa81ebb115cb4fcea4c90ed82446326cce7d35
[root@VM_0_14_centos ~]# docker run -it -d --name centos1 --network my-net centos
a43d83dbbde5827aeb3a66bab0e954df3b95a157dc0aea218cb23565af9655ce
[root@VM_0_14_centos ~]# docker run -it -d --name centos2 --network my-net centos
4f59c5ed14e075a1ef05468d9bfd75fe02fd210b3b580c8b0994bb3c0310a80e
[root@VM_0_14_centos ~]# docker exec -it centos1 /bin/bash
[root@a43d83dbbde5 /]# ping centos2
PING centos2 (172.18.0.3) 56(84) bytes of data.
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.112 ms
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.058 ms
64 bytes from centos2.my-net (172.18.0.3): icmp_seq=4 ttl=64 time=0.056 ms
^C
--- centos2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.056/0.071/0.112/0.025 ms
[root@a43d83dbbde5 /]# 

上面演示了创建一个bridge类型网络my-net

然后创建了两个容器centos1、centos2都连接到这个容器,然后进入centos1,使用ping centos2成功。

Docker Compose

如果有多个容器之间需要相互连接,推荐使用Docker ComposeDocker Compose不是本篇文章的内容,后面文章会对他进行专门讲解。

Docker的四种网络模式

docker run的时候可以通过--net=xxx或者--network=xxx来指定使用哪一种网络模式启动容器。总共有以下四种模式:

bridge模式网络

这是Docker默认的网络模式,在该模式中,Docker守护进程创建了一个虚拟以太网桥docker0,附加骑上的任何网卡之间能自动转发数据包。默认情况下,守护进程会创建一对对等接口,将其中一个接口设置为容器的eth0接口,另一个接口放置在宿主机的命名空间,从而将宿主机上的所有容器都连接到这个内部网络。同时,守护进程还会从网桥的私有地址空间中分配一个IP地址和子网给该容器。

host模式网络

该模式中将禁用Docker容器的网络隔离,容器共享宿主机的网络命名空间,直接暴露在公网中,容器会继承宿主机的IP地址。使用host模式会将容器直接暴露在公网,会存在安全隐患。

container模式网络

该模式中,容器会使用另一个容器的网络命名空间。使用方式为:--net=container:containername

none模式网络

该模式将容器放置在自己的网络栈中,并不进行任何配置,该模式实际上是关闭了容器的网络功能。

Docker网络操作

Docker默认会创建一个docker0网桥,在启动docker服务的时候,可以对docker0进行配置:

  • --bip=CIDR IP地址加掩码,如:192.168.1.5/24
  • --mtu=BYTES 覆盖默认的mtu(接口允许接收最大传输单元)配置

除此之外,Docker还提供了很多对于网络的操作命令:

  • docker network create

    创建一个网络,用法如下:

    docker network create -d bridge --subnet 172.25.0.0/16 mynet
    

    可以通过-d参数指定网络模式,同时--subnet指定子网的ip以及掩码。最后是网络名称

  • docker network connect

    连接一个容器到网络中,用法如下:

    docker network connect mynet containername
    
  • docker network ls

    显示所有网络:

    [root@VM_0_14_centos ~]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    1743c0f6d043        bridge              bridge              local
    99fefa50be75        host                host                local
    d90fc3d8515b        my-net              bridge              local
    c42853bb3a87        none                null                local

    可以看到默认情况下docker会存在3个网络分别使用对应的网络模型名称作为网络名称。在启动容器的时候可以使用--net--network来指定使用哪个网络,默认情况下使用bridge网络,它是一个bridge类型的网络。

  • docker network rm

    移除网络

  • docker networdk disconnect

    容器和网络断开。

  • docker network inspect

    查看网络详情。

总结

本篇文章介绍了一些对于Docker中网络的理解。包括Docker中默认的网络配置,以及如何对Docker中的网络进行管理等。

参考:

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐