## Docker 網絡實現
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` 參數。
```bash
$ docker run -i -t --rm --net=none base /bin/bash
root@63f36fc01b5f:/#
```
在本地主機查找容器的進程 id,并為它創建網絡命名空間。
```bash
$ 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 和子網掩碼信息。
```bash
$ ip addr show docker0
21: docker0: ...
inet 172.17.42.1/16 scope global docker0
...
```
創建一對 “veth pair” 接口 A 和 B,綁定 A 到網橋 `docker0`,并啟用它
```bash
$ sudo ip link add A type veth peer name B
$ sudo brctl addif docker0 A
$ sudo ip link set A up
```
將B放到容器的網絡命名空間,命名為 eth0,啟動它并配置一個可用 IP(橋接網段)和默認網關。
```bash
$ 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 簡介
- 什么是 Docker
- 為什么要用 Docker
- 基本概念
- 鏡像
- 容器
- 倉庫
- 安裝 Docker
- Ubuntu
- Debian
- CentOS
- Raspberry Pi
- macOS
- Windows PC
- 鏡像加速器
- 使用鏡像
- 獲取鏡像
- 列出鏡像
- 刪除本地鏡像
- 利用 commit 理解鏡像構成
- 使用 Dockerfile 定制鏡像
- Dockerfile 指令詳解
- COPY 復制文件
- ADD 更高級的復制文件
- CMD 容器啟動命令
- ENTRYPOINT 入口點
- ENV 設置環境變量
- ARG 構建參數
- VOLUME 定義匿名卷
- EXPOSE 暴露端口
- WORKDIR 指定工作目錄
- USER 指定當前用戶
- HEALTHCHECK 健康檢查
- ONBUILD 為他人作嫁衣裳
- 參考文檔
- Dockerfile 多階段構建
- 其它制作鏡像的方式
- 實現原理
- 操作容器
- 啟動
- 守護態運行
- 終止
- 進入容器
- 導出和導入
- 刪除
- 訪問倉庫
- Docker Hub
- 私有倉庫
- 私有倉庫高級配置
- Nexus 3
- 數據管理
- 數據卷
- 掛載主機目錄
- 使用網絡
- 外部訪問容器
- 容器互聯
- 配置 DNS
- 高級網絡配置
- 快速配置指南
- 容器訪問控制
- 端口映射實現
- 配置 docker0 網橋
- 自定義網橋
- 工具和示例
- 編輯網絡配置文件
- 實例:創建一個點到點連接
- Docker 三劍客之 Compose 項目
- 簡介
- 安裝與卸載
- 使用
- 命令說明
- Compose 模板文件
- 實戰 Django
- 實戰 Rails
- 實戰 WordPress
- Docker 三劍客之 Machine 項目
- 安裝
- 使用
- Docker 三劍客之 Docker Swarm
- Swarm mode
- 基本概念
- 創建 Swarm 集群
- 部署服務
- 使用 compose 文件
- 管理敏感數據
- 管理配置信息
- 滾動升級
- 安全
- 內核命名空間
- 控制組
- 服務端防護
- 內核能力機制
- 其它安全特性
- 總結
- 底層實現
- 基本架構
- 命名空間
- 控制組
- 聯合文件系統
- 容器格式
- 網絡
- Etcd 項目
- 簡介
- 安裝
- 集群
- 使用 etcdctl
- CoreOS 項目
- 簡介
- 工具
- 快速搭建 CoreOS 集群
- Kubernetes 項目
- 簡介
- 快速上手
- 基本概念
- kubectl 使用
- 架構設計
- Mesos - 優秀的集群資源調度平臺
- Mesos 簡介
- 安裝與使用
- 原理與架構
- Mesos 配置項解析
- 日志與監控
- 常見應用框架
- 本章小結
- 容器與云計算
- 簡介
- 亞馬遜云
- 騰訊云
- 阿里云
- 小結
- 實戰案例-操作系統
- Busybox
- Alpine
- Debian Ubuntu
- CentOS Fedora
- 本章小結
- 實戰案例-CI/CD
- Drone
- Docker 開源項目
- LinuxKit
- 附錄
- 附錄一:常見問題總結
- 附錄二:熱門鏡像介紹
- Ubuntu
- CentOS
- MySQL
- MongoDB
- Redis
- Nginx
- WordPress
- Node.js
- 附錄三:Docker 命令查詢
- 附錄四:Dockerfile 最佳實踐
- 附錄五:資源鏈接
- 附錄六:Docker 中文資源