[docker] 浅谈Docker:网络模式及从容器内部访问宿主机的IP地址
0 序
- 本文系转载参考文献,属于非原创的笔记类博文。
- 最新结论:从Docker容器内部访问宿主的IP地址的几种方法,推荐 基于 Bridge 模式 +
--link访问别的服务 +172.16.0.1(访问宿主机)。
1 Docker的网络模式
- docker是比较流行的容器技术,docker镜像方便程序员对应用统一的要求,打包部署便捷。但是不足的地方在于docker的网络方面。
- docker有4种网络模式,分别是:
- host模式
- container模式
- none模式
- bridge模式
-
分别使用
-net, --network指定。如:-net=host、-net=container(容器名或ID)、-net=bridge指定各种网络模式。 -
Docker 默认网络
Docker安装后,默认会创建下面三种网络类型:
[root@172 /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
7bae40b7ba3b bridge bridge local
a76157f2257d host host local
c8e7302eb8c8 none null local
启动 Docker 的时候,用
--network参数,可以指定网络类型,如:
[root@172 /]# docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash
1.1 Host模式
简介
- 在
host模式下,容器与宿主机共享Network Namespace。
- 容器不会获得独立的网络命名空间,而是使用宿主机的IP地址和端口。
这样,容器可以直接使用宿主机的网络接口与外界通信,网络性能较好,但容器之间的网络隔离性较差。
简言之:与宿主机在同一网络中,但是没有独立的IP地址。
- docker使用Linux的Namespace隔离网络等设施。
- 一个Network Namespace 提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。
- 当我们启动容器指定其网络模式为host时,启动指定命令如下:
docker run --name xxx --net=host xxxx
docker run -itd --name test1 --network host centos:7 /bin/bash
此处使用
-net指定docker容器所使用的网络模式。
- 在使用host模式时,容器将不会获得一个独立的Network Namespace,不会模拟出自己的网卡、配置自己的ip等。而是和宿主机共用一个namespace。所有此模式使用的网络和宿主机上的网络是相同的。
使用
- 在运行容器时,可以使用
--network=host选项,这将使得容器共享【宿主机】的网络命名空间,使得容器内部可以直接访问宿主的IP地址。
Docker 提供了一个主机网络,让容器可以共享主机的网络堆栈。这种方法意味着容器内的本地主机解析为物理主机,而不是容器本身。通过添加 --network=host 标志与主机网络一起启动容器:
docker run --network=host your_image_name
例如:
docker run -d --network=host my-container:latest
build docker镜像时,使用宿主机网络
参考文献: docker build - network 解决 docker build timeout - geekdaxue.co
- 使用 Dockerfile 来 docker build 镜像时,默认使用的 bridge 网络环境;而 RUN 等命令经常需要联网下载依赖,由于公司加密软件的限制,造成RUN命令使用bridge时无法联网
- 想到使用 host 网络应该可以上网,host网络中,docker 容器没有自己的网卡和ip,不使用birdge网络,直接使用本机的网络;只要本机可以上网,docker build时的RUN命令就可以使用网络
docker build --network host .
--network标志指定在构建过程中,RUN命令使用哪种网络模式。
1.2 container模式
- container模式是将新创建的容器和已经存在的容器共享一个Network Namespace ,而不是和宿主机共享。
- 在创建容器时指定容器,就会共享被指定的容器的ip、端口等。两个容器仅仅是网络共享,其他当面还是隔离的,如文件系统、进程列表等等。俩个容器之间通过IO网卡进行本地通信。
1.3 none模式
- 此模式下,docker拥有自己的网络命名空间,但是不会为容器进行任何的网络配置,容器没有网卡、ip、路由等信息,需要我们自己为docker容器添加网卡配置ip,不会创建网络设备。
1.4 bridge模式【默认模式】
简介
-
bridge模式是docker默认的网络模式,此模式创建一对虚拟网络设备,一半在容器上,一半再虚拟网络桥上。为每一个容器分配NetWork Namespace、网卡、ip等信息,将docker容器连接到虚拟网桥上。 -
此模式比较常用,在我们的docker服务启动时,主机上会创建一个名为docker0的虚拟网桥,在主机上启动的容器服务都会连接到这个虚拟网桥上,和交换机的原理有些类似,此时主机上的容器通过此"交换机"连接在二层网络中。
-
再后就是为容器分配ip,Docker会从RFC1918(私有网络地址分配)所定义的私有ip网段中选择一个核宿主机不同的ip地址和子网分配给docker0,连接到docker0的容器就从此子网中选择一个未占用的ip使用。
一般会使用
172.17.0.0/16这个网段,并将172.17.0.0/16分配给docker0网桥。
在宿主机上使用ifconfig可以看到docker0,可以看做是网桥的管理接口,在宿主机上作为一块虚拟网卡使用。在其他大佬的文章上找到一张图,很清晰的画出了网络拓扑。宿主机的ip地址为eth0

- 常用的还是
bridge模式,容器之间可以通信,创建容器时默认创建网络模式。
使用
- 使用特殊的宿主地址
在Linux系统中,可以使用特殊的IP地址
172.17.0.1来代表【宿主机】,这个IP地址通常用于Docker默认的网络桥接模式中。

- 案例1:下面画一张拓扑图来详细地讲述docker内的容器是如何进行通信的。

如上图所示,在宿主机中,在运行容器时默认采取【bridge网络模式】,当docker服务启动时会创建docker0网卡,所有的容器借助于此虚拟网卡和宿主机以及外界进行通信,容器之间可以直接通信。
上述方式需要进入容器中查看
/etc/hosts文件中的主机的信息,显得过于麻烦,在运行docker容器时可以直接将容器的ip对应于域名,容器之间互相访问通信时直接根据域名通信即可。
- 使用
docker --link模式来实现,实现方式 如下,使用docker跑起乱来一个nginx容器
再跑起来一个基于centos的容器,在此时使用–link命令在此容器中直接添加nginx容器的域名解析信息(将mynginx的172.17.0.2解析为nginx1,之后在centos创建的容器中可以直接访问nginx1即可访问mynginx容器),操作如下。
docker run --name mycentos -id --link mynginx:nginx1 centos
创建完成之后进入mycentos容器中,使用curl nginx1就可直接访问mynginx容器中的服务了,方便快捷。
2 补充:【挂载宿主的网络命名空间到容器内部】
- 可以手动挂载宿主的网络命名空间到容器内部。这种方法比较复杂,但是也是可行的。可以使用nsenter命令来实现这一点。
- 首先,需要获取宿主的网络命名空间ID:
sudo docker inspect --format '{{ .State.Pid }}' <container_id_or_name>
- 然后,使用
nsenter命令将容器加入到宿主的网络命名空间中:
sudo nsenter --target <host_pid> --net <your_command>
这样,就可以在容器内部直接访问宿主的网络。
X 参考文献
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号