Docker 的网络实现其实就是利用了 Linux 上的网络名字空间和虚拟网络设备(特别是 veth pair)。建议先熟悉了解这两部分的基本概念再阅读本章。

基本原理

首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。

Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势之一是转发效率较高。 Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中。对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要快很多。

Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做 veth pair)。

创建网络参数

Docker 创建一个容器的时候,会执行如下操作:

  • 创建一对虚拟接口,分别放到本地主机和新容器中;
  • 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 veth65f9;
  • 容器一端放到新容器中,并修改名字作为 eth0,这个接口只在容器的名字空间可见;
  • 从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 veth65f9。

完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。

可以在 docker run 的时候通过 --net 参数来指定容器的网络配置,有4个可选值:

  • --net=bridge 这个是默认值,连接到默认的网桥。
  • --net=host 告诉 Docker 不要将容器网络放到隔离的名字空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用 --privileged=true,容器会被允许直接配置主机的网络堆栈。
  • --net=container:NAME_or_ID 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 lo 环回接口通信。
  • --net=none 让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。

网络配置细节

用户使用 --net=none 后,可以自行配置网络,让容器达到跟平常一样具有访问网络的权限。通过这个过程,可以了解 Docker 配置网络的细节。

首先,启动一个 /bin/bash 容器,指定 --net=none 参数。

$ sudo docker run -i -t --rm --net=none base /bin/bash
root@63f36fc01b5f:/#

在本地主机查找容器的进程 id,并为它创建网络命名空间。

$ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f
2778
$ pid=2778
$ sudo mkdir -p /var/run/netns
$ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid

检查桥接网卡的 IP 和子网掩码信息。

$ ip addr show docker0
21: docker0: ...
inet 172.17.42.1/16 scope global docker0
...

创建一对 “veth pair” 接口 A 和 B,绑定 A 到网桥 docker0,并启用它

$ sudo ip link add A type veth peer name B
$ sudo brctl addif docker0 A
$ sudo ip link set A up

将B放到容器的网络命名空间,命名为 eth0,启动它并配置一个可用 IP(桥接网段)和默认网关。

$ sudo ip link set B netns $pid
$ sudo ip netns exec $pid ip link set dev B name eth0
$ sudo ip netns exec $pid ip link set eth0 up
$ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0
$ sudo ip netns exec $pid ip route add default via 172.17.42.1

以上,就是 Docker 配置网络的具体过程。

当容器结束后,Docker 会清空容器,容器内的 eth0 会随网络命名空间一起被清除,A 接口也被自动从 docker0 卸载。

此外,用户可以使用 ip netns exec 命令来在指定网络名字空间中进行配置,从而配置容器内的网络。

Docker 网络的更多相关文章

  1. 理解Docker(5):Docker 网络

    本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  2. docker网络配置方法总结

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

  3. 【转】Docker网络详解及pipework源码解读与实践

    好文必转 原文地址: http://www.infoq.com/cn/articles/docker-network-and-pipework-open-source-explanation-prac ...

  4. Docker网络模式

    [编者的话] 本文是<Docker网络及服务发现>一书的一个章节,介绍了搭建Docker单主机网络的基础内容.关于Docker网络的更多内容,包括多主机的网络,请参考该书的其他章节. @C ...

  5. docker网络-如何让外部网络访问容器资源

    docker网络-如何让外部网络访问容器资源 安装httpd 服务: docker:/root# docker exec -it f63b2633d146 bash bash-4.1# yum ins ...

  6. docker网络解析

    Docker概念和默认网络 什么是Docker网络呢?总的来说,网络中的容器们可以相互通信,网络外的又访问不了这些容器.具体来说,在一个网络中,它是一个容器的集合,在这个概念里面的一个容器,它会通过容 ...

  7. docker网络访问(三)

    docker网络访问 ifconfig查看网卡,启动docker的时候,docker会帮我们创建一个docker0的网桥. 1.随机映射 docker run -P 2.指定映射 -p hostPor ...

  8. [Docker网络]模拟一台交换机的拓扑

    [Docker网络]模拟一台交换机的拓扑 本例主要对Docker网络进行实际运用. 背景介绍 一台虚拟机如何模拟成一台多端口交换机分别连接多台虚拟机? bridge网桥技术 实验准备 docker d ...

  9. Docker 网络之理解 bridge 驱动

    笔者在前文<Docker 网络之进阶篇>中介绍了 CNM(Container Network Model),并演示了 bridge 驱动下的 CNM 使用方式.为了深入理解 CNM 及最常 ...

  10. Docker 网络之进阶篇

    笔者在<Docker 基础 : 网络配置>一文中简单介绍了容器网络的基本用法,当时网络的基本使用方式还处于 --link 阶段.时过境迁,随着 docker 的快速发展,其网络架构也在不断 ...

随机推荐

  1. python/ Django之中间件

    python/ Django之中间件 一.中间件 中间件共分为: (1)process_request(self,request) (2)process_view(self, request, cal ...

  2. python网络编程基础(一)

    一.C/S架构 客户端/服务端架构 二.OSI七层架构 七层模型,亦称OSI(Open System Interconnection)参考模型,是参考模型是国际标准化组织(ISO)制定的一个用于计算机 ...

  3. orchard-1.9.2-1.10.2汉化

    安装 首先从github上下载orchard源代码:https://github.com/OrchardCMS/Orchard(下载版本最新的1.10.2) 使用vs2017打开源代码,运行进入安装界 ...

  4. JS字符串和数组常用方法

    1.indexOf() – 返回字符串中一个字符第一处出现的索引,接收2个参数:要查找的字符,从哪个位置开始查找:.lastIndexOf()--返回字符串中某一个字符最后一次出现的索引值. 如果没有 ...

  5. 前端开发必备之Chrome开发者工具(下篇)

    本文介绍的 Chrome 开发者工具基于 Chrome 65版本,如果你的 Chrome 开发者工具没有下文提到的那些内容,请检查下 Chrome 的版本 本文是 前端开发必备之Chrome开发者工具 ...

  6. 闲聊 Exp/Imp 命令使用

    1.Exp/Imp 命令可用的参数: 2.userid 参数必须跟在 Exp/Imp 命令的后面,可以省略,如 Exp Userid=用户名/密码@数据库实例名 或者 Exp 用户名/密码@数据库实例 ...

  7. .Net中集合排序还可以这么玩

    背景: public class StockQuantity { public StockQuantity(string status, DateTime dateTime, int quantity ...

  8. 使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法

    数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...

  9. [USACO 04OPEN]MooFest

    Description 约翰的N 头奶牛每年都会参加“哞哞大会”.哞哞大会是奶牛界的盛事.集会上的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等.它们参加活动时会聚在一起,第i 头奶牛的坐标为Xi,没 ...

  10. [Luogu 3810]三维偏序

    Description 有 $ n $ 个元素,第 $ i $ 个元素有 $ a_i $ .$ b_i $ .$ c_i $ 三个属性,设 $ f(i) $ 表示满足 $ a_j \leq a_i $ ...