Docker笔记(四)网络
本笔记是记录一些学习微信公众号CloudMan的Docker的文章。本篇介绍容器的网络。
网络
Docker 安装时会自动在 host 上创建三个网络,可用 docker network ls 命令查看:
[root@finix-docker2 docker]# docker network ls
NETWORK ID NAME DRIVER SCOPE
6150b3bd13e6 bridge bridge local
834acba0d887 host host local
30e8599df623 none null local
none 网络
故名思议,none 网络就是什么都没有的网络。挂在这个网络下的容器除了 lo,没有其他任何网卡。
容器创建时,可以通过 –network=none 指定使用 none 网络。
host 网络
连接到 host 网络的容器共享 Docker host 的网络栈,容器的网络配置与 host 完全一样。
可以通过 –network=host 指定使用 host 网络。
在容器中可以看到 host 的所有网卡,并且连 hostname 也是 host 的。
直接使用 Docker host 的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择 host 网络。
不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host 上已经使用的端口就不能再用了。
bridge网络
Docker 安装时会创建一个命名为 docker0 的 linux bridge。如果不指定–network,创建的容器默认都会挂到 docker0 上。
容器创建时,docker 会自动从 172.17.0.0/16 中分配一个 IP,这里 16 位的掩码保证有足够多的 IP 可以供容器使用。
当前 docker0 上没有任何其他网络设备,创建一个容器看看有什么变化:
一个新的网络接口 veth28c57df 被挂到了 docker0 上,veth28c57df就是新创建容器的虚拟网卡。
用ifconfig看,容器有一个网卡 eth0@if34. 为什么不是veth28c57df 呢?
实际上 eth0@if34 和 veth28c57df 是一对 veth pair.
veth pair 是一种成对出现的特殊网络设备。 可以把它们想象成由一根虚拟网线连接起来的一对网卡,一张网卡(eth0@if34)在容器中,另一张网卡(veth28c57df)挂在网桥 docker0 上,其效果就是将 eth0@if34 也挂在了 docker0 上。
如何自定义容器的网络
Docker 提供三种 user-defined 网络驱动:bridge, overlay 和 macvlan.
overlay 和 macvlan 用于创建跨主机的网络,后面有章节单独讨论。
可通过 bridge 驱动创建类似前面默认的 bridge 网络,例如:
[root@finix-docker2 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242c27c5710 no vethf649665[root@finix-docker2 ~]# docker network create --driver bridge my_net
be9999cfd17c4fa7e9e5964fc0ab0927a54581ae1c7766ed6a2826b0e3b1f7fb[root@finix-docker2 ~]# brctl show
bridge name bridge id STP enabled interfaces
br-be9999cfd17c 8000.024229c5bc26 no
docker0 8000.0242c27c5710 no vethf649665
注:
如果docker host是cloud image的CentOS,那么可能没有安装brctl. 可以运行 yum install bridge-utils 来安装。
上面新增了一个网桥 br-be9999cfd17c,这里 be9999cfd17c 正好新建 bridge 网络 my_net 的短 id。
执行 docker network inspect 查看一下 my_net 的配置信息:
[root@finix-docker2 ~]# docker network inspect my_net
[{"Name": "my_net","Id": "be9999cfd17c4fa7e9e5964fc0ab0927a54581ae1c7766ed6a2826b0e3b1f7fb","Created": "2017-12-31T15:32:43.344450519Z","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "172.18.0.0/16","Gateway": "172.18.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {},"Labels": {}}
]
这里 172.18.0.0/16 是 Docker 自动分配的 IP 网段。
可以自己指定 IP 网段吗?
答案是:可以。只需在创建网段时指定 –subnet 和 –gateway 参数:
[root@finix-docker2 ~]# docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net_2
502c09fbf79f07e422e0950d3eca81deb9fd5ddf295a2e2281f3dba863591002
[root@finix-docker2 ~]# docker network inspect my_net_2
[{"Name": "my_net_2","Id": "502c09fbf79f07e422e0950d3eca81deb9fd5ddf295a2e2281f3dba863591002","Created": "2017-12-31T15:38:15.288155518Z","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "172.22.16.0/24","Gateway": "172.22.16.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {},"Labels": {}}
]
这里我们创建了新的 bridge 网络 my_net_2,网段为 172.22.16.0/24,网关为 172.22.16.1。
与前面一样,网关在 my_net_2 对应的网桥 br-502c09fbf79f 上。运行brctl show可看到。
容器要使用新的网络,需要在启动时通过 –network 指定:
[root@finix-docker2 ~]# docker run -it --network my_net_2 busybox
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:16:10:02 brd ff:ff:ff:ff:ff:ffinet 172.22.16.2/24 scope global eth0valid_lft forever preferred_lft forever
容器分配到的 IP 为 172.22.16.2。
到目前为止,容器的 IP 都是 docker 自动从 subnet 中分配,能否指定一个静态 IP 呢?
答案是:可以,通过–ip指定。
[root@finix-docker2 ~]# docker run -it --network=my_net_2 --ip=172.22.16.10 busybox
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
36: eth0@if37: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:16:10:0a brd ff:ff:ff:ff:ff:ffinet 172.22.16.10/24 scope global eth0valid_lft forever preferred_lft forever
/ #
注:只有使用 –subnet 创建的网络才能指定静态 IP。
理解容器之间的连通性
前提:
两个 busybox 容器都挂在 my_net2 上,它们之间能够互通。而httpd挂在默认的bridge网络docker0上。
my_net2 与默认 bridge 网络 docker0 能通信吗?不能。
不同的网络如果加上路由应该就可以通信了吧?
确实,如果 host 上对每个网络的都有一条路由,同时操作系统上打开了 ip forwarding,host 就成了一个路由器,挂接在不同网桥上的网络就能够相互通信。
看看 ip forwarding:
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
ip forwarding已经启用了。但此时为何mynet2和docker0为何不能连通呢?再看看 iptables:
# iptables-save
......
-A DOCKER-ISOLATION -i br-5d863e9f78b6 -o docker0 -j DROP
-A DOCKER-ISOLATION -i docker0 -o br-5d863e9f78b6 -j DROP
......
原因找到了:iptables DROP 掉了网桥 docker0 与 br-5d863e9f78b6 之间双向的流量。
从规则的命名 DOCKER-ISOLATION 可知 docker 在设计上就是要隔离不同的 netwrok。
怎样才能让 busybox 与 httpd 通信呢?
答案是:为 httpd 容器添加一块 my_net2 的网卡。这个可以通过docker network connect 命令实现。
docker network connect my_net2 <short id of httpd container>
通过ip addr命令可以看出,httpd容器中新增了一块网卡,它连到了my_net2. 这样,httpd容器和2个busybox容器就可以互相连通了。
容器间通信的3种方式
方式一 加入同一个网络
两个容器要能通信,必须要有属于同一个网络的网卡。满足这个条件后,容器就可以通过 IP 交互了。
具体做法是在容器创建时通过 –network 指定相应的网络,或者通过 docker network connect 将现有容器加入到指定网络。
可参考上一节 httpd 和 busybox 的例子,这里不再赘述。
方式二 使用内嵌的DNS server
从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。
方法很简单,只要在启动时用 –name 为容器命名就可以了。
docker run -it --network=my_net2 --name=bbox1 busybox
docker run -it --network=my_net2 --name=bbox2 busybox
然后,bbox2 就可以直接 ping 到 bbox1 了。
使用 docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的。
方式三 joined容器
joined 容器非常特别,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。
举例如下:
先创建一个 httpd 容器,名字为 web1。
docker run -d -it --name=web1 httpd
然后创建 busybox 容器并通过 –network=container:web1 指定 jointed 容器为 web1:
docker run -it --network=container:web1 busybox
busybox 和 web1 的网卡 mac 地址与 IP 完全一样,它们共享了相同的网络栈。busybox 可以直接用 127.0.0.1 访问 web1 的 http 服务。
joined 容器非常适合以下场景:
- 不同容器中的程序希望通过 loopback 高效快速地通信,比如 web server 与 app server。
- 希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序。
容器如何访问外部世界
如果docker host可以访问外网,那么容器默认也能访问外网。
原理如下:
busybox容器位于docker0这个bridge网络中,当busybox的ping包往外发的时候,首先由NAT功能将该包的源地址替换成docker host的地址再发送出去。
docker0 收到 busybox 的 ping 包,源地址为容器 IP 172.17.0.2,这没问题,交给 MASQUERADE 处理。这时,在 docker host 的网卡上我们看到了变化:
ping 包的源地址变成了主机网卡的 IP 10.0.2.15
External Network <– docker host NIC <– NAT <– docker0 <– busybox
外部世界如何访问容器
答案是:端口映射
docker 可将容器对外提供服务的端口映射到 host 的某个端口,外网通过该端口访问容器。容器启动时通过-p参数映射端口。
容器启动后,可通过 docker ps 或者 docker port 查看到 host 映射的端口。
除了映射动态端口,也可在 -p 中指定映射到 host 某个特定端口,例如可将 container port 映射到 host port :
docker run -d -p <host port>:<container port> httpd
每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量:
ps -elf | grep docker-proxy
Docker笔记(四)网络相关推荐
- Docker笔记四 发布自制DockerImage 到 Dockerhub
Docker笔记 四 发布自制DockerImage 到 Dockerhub 1.注册Dockerhub账号 https://hub.docker.com/ 2.制作准备上传的dockerp_w_pi ...
- kali linux学习笔记(四) : 网络端口大全介绍
端口大全介绍 2端口:管理实用程序 3端口:压缩进程 5端口:远程作业登录 7端口:回显 9端口:丢弃 11端口:在线用户 13端口:时间 17端口:每日引用 18端口:消息发送协议 19端口:字符发 ...
- Docker(十四):Docker:网络模式详解
Docker作为目前最火的轻量级容器技术,牛逼的功能,如Docker的镜像管理,不足的地方网络方面. Docker自身的4种网络工作方式,和一些自定义网络模式 安装Docker时,它会自动创建三个网络 ...
- Docker学习四:Docker 网络
前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...
- Docker的四种网络模式
docker run创建Docker容器时,可以用–net选项指定容器的网络模式,Docker有以下4种网络模式: bridge模式:使用–net =bridge指定,默认设置: host模式:使用– ...
- 5、Docker 的四种网络模式
5.1 Docker 的四种网络模式 网络模式 网络配置 说明 host(开放式网络模式) –network host 容器和宿主机共享 Network namespace container(联合挂 ...
- docker学习笔记(三)docker中的网络
目录 Linux中的网卡 Network Namespace Docker中的Bridge网络 使用自定义Bridge网络创建容器 Container中的其他网络 Host网络 None网络 Linu ...
- docker系列四之网络
基础材料 CentOS7.6 minimal 关闭selinux 关闭swap分区 关闭NetworkManager 关闭firewalld Docker-ce 18.09.0 Docker支持的网 ...
- Docker教程(四) Docker镜像构建
Docker教程(四) Docker镜像构建 本文链接:https://blog.csdn.net/yuan_xw/article/details/77744272 Docker教程(四) Docke ...
最新文章
- 那些按烂的Linux命令集合贴
- 基于模糊聚类的色彩迁移算法
- Hibernate实现对多个表进行关联查询
- 2020-12-17 Halcon初学者知识【4】区域和分割
- CodeForces - 1332B Composite Coloring(数论+构造)
- 理解音视频 PTS 和 DTS
- mysql标识列从一开始_mysql中标识列是什么意思有什么用
- mysql 事务回滚_简短截说阐述redis中事务的使用
- Java Web的分页工具类
- a - 数据结构实验之串一:kmp简单应用_数据结构(C语言版)_笔记_3
- 计算机专业小米笔记本推荐,小米笔记本电脑怎么样有哪些型号,哪款性价比高?...
- BZOJ 4565 字符合并 (区间 DP 状压 DP)
- 地方论坛门户网站运营之我见-上篇
- 浏览器开发者模式下你不可错过的Network面板知识
- 迷你图书管理器1.2 - 面向对象+集合
- 现代 React Web 开发实战——kanban实现卡片拖拽
- LeetCode刷题之575.分糖果
- java圆的面积_JAVA求圆的面积
- IP-Guard安全U盘使用说明书
- Leetcode 组合总和II