一、端口暴露

Docker 容器更多情况下是用来运行 Web 应用的,所以要如何访问到容器中的 Web 服务呢?比如我们现在运行一个 nginx 容器服务:

$ docker run --name webserver -d nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
8d691f585fa8: Pull complete
5b07f4e08ad0: Pull complete
abc291867bca: Pull complete
Digest: sha256:922c815aa4df050d4df476e92daed4231f466acc8ee90e0e774951b0fd7195a4
Status: Downloaded newer image for nginx:latest
e8b034c01f4024162cefc45006738fce85b3fa1b717a6ff24520c0fcfabaf5b6

nginx 镜像没有指定 tag 标签,则默认就是拉取nginx:latest镜像;其中--name参数指定容器的名称,不指定则是随机的容器名,运行成功后可以通过docker ps命令查看容器信息:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8b034c01f40 nginx "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp webserver

但是我们要怎么去访问这个 nginx 服务呢?实际上在我们启动容器的时候,Docker 就会为我们的容器分配一个 IP 地址,我们可以通过如下命令来获取容器的 IP 地址:

$ docker inspect webserver |grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.4",
"IPAddress": "172.17.0.4",

其中的 172.17.0.4就是容器 webserver 的地址,这个时候我们可以通过该地址访问到 nginx 服务:

$ curl http://172.17.0.4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>
</html>

但是这样不够方便,因为启动容器的代价很小,所以容器的 IP 这些经常变动,是否能够通过宿主机的方式去访问呢?实际上是可以的,我们可以通过如下命令重新启动一个新的容器:

$ docker rm -f webserver
$ docker run --name webserver -d -p 80:80 nginx

我们在启动容器的时候添加了一个新的参数-p 8080:80,这个参数的意思是将宿主机的 8080 端口和容器的 80 端口进行绑定,这样我们就可以通过宿主机的 8080 端口来访问容器服务了。

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
89e105d56215 nginx "nginx -g 'daemon of…" About a minute ago Up About a minute 0.0.0.0:8080->80/tcp webserver
$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>
</html>

二、Bridge 模式

当 Docker 进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。从 docker0 子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为 eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。可以通过brctl show命令查看:

$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024286df8f39 no veth1040b0a

bridge 模式是 docker 的默认网络模式,使用docker run -p时,实际上是通过 iptables 做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。bridge模式如下图所示:​​



比如现在我们运行一个 busybox 容器:

$ docker run -tid --net=bridge --name docker_bri busybox top
$ brctl show
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024286df8f39 no veth1040b0a

然后进入到容器内部去查看网络情况,这里我们需要使用到一个新的命令docker exec,用来进入容器内部,要记住我们要进行终端交互,所以要带上-it两个参数:

$ docker exec -it docker_bri /bin/sh
/ # ifconfig -a
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:05
inet addr:172.17.0.5 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) / # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0

可以通过ip link show命令查看到对应的 veth pair 对名称

通过上面的命令可以验证我们前面提到的 bridge 模式原理。

三、自定义网络

另外我们可以通过自定义的 Docker 网络来连接多个容器,而不是使用--link命令,比如现在我们有一个新的容器想要和上面的 docker_bri 容器建立互连关系,之前我们可以使用 --link 命令:

$ docker run -tid --link docker_bri --name docker_bri1 busybox top
2cba17dd1326c2c82d8fa415588a0169e7291d1a44d2accaff25d50216830777
$ docker exec -it docker_bri1 /bin/sh
/ # ping docker_bri
PING docker_bri (172.17.0.5): 56 data bytes
64 bytes from 172.17.0.5: seq=0 ttl=64 time=0.194 ms
64 bytes from 172.17.0.5: seq=1 ttl=64 time=0.156 ms

我们可以看到在新创建的容器上可以访问到我们连接的容器,但是反过来却不行了,因为--link是单方面的:

$ docker exec -it docker_bri /bin/sh
/ # ping docker_bri1
ping: bad address 'docker_bri1'
/ #

这个时候我们可以通过自定义网络的方式来实现互联互通,首先创建一个自定义的网络:

$ docker network create -d bridge my-net

然后我们使用自定义的网络运行一个容器:

$ docker run -it --rm --name busybox1 --network my-net busybox sh

打开终端再运行一个容器:

$ docker run -it --rm --name busybox2 --network my-net busybox sh

然后我们通过 ping 来证明 busybox1 容器和 busybox2 容器建立了互联关系。 在 busybox1 容器输入以下命令:

/ # ping busybox2
PING busybox2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms

用 ping 来测试连接 busybox2 容器,它会解析成 172.19.0.3。 同理在 busybox2 容器执行 ping busybox1,也会成功连接到:

/ # ping busybox1
PING busybox1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.064 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.143 ms

这样,busybox1 容器和 busybox2 容器建立了互联关系,如果你有多个容器之间需要互相连接,推荐使用后面的 Docker Compose。

四、Host 模式

如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。 Host模式如下图所示:



使用 host 模式也很简单,只需要在运行容器的时候指定 --net=host 即可。

五、Container 模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。 Container 模式如下图所示:



在运行容器的时候指定 --net=container:目标容器名 即可。实际上我们后面要学习的 Kubernetes 里面的 Pod 中容器之间就是通过 Container 模式链接到 pause 容器上面的,所以容器直接可以通过 localhost 来进行访问。

六、None 模式

使用 non e模式,Docker 容器拥有自己的 Network Namespace,但是并不为Docker 容器进行任何网络配置。也就是说这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。 None模式示意图如下所示:



选择这种模式,一般是用户对网络有自己特殊的需求,不希望 docker 预设置太多的东西。

下一篇将介绍Docker数据共享与持久化

(转发请注明出处:http://www.cnblogs.com/zhangyongli2011/ 如发现有错,请留言,谢谢)

Docker基本操作(端口?网络模式?)(五)的更多相关文章

  1. [转帖]Docker四种网络模式

    Docker(十四)-Docker四种网络模式 https://www.cnblogs.com/zhuochong/p/10069293.html 计算机网络相关的知识 非常有用.. Docker 安 ...

  2. Docker 四种网络模式

    原文 https://www.cnblogs.com/gispathfinder/p/5871043.html 我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络 ...

  3. Docker学习第四天(Docker四种网络模式)

    Docker四种网络模式 实现原理 Docker使用Linux桥接(参考<Linux虚拟网络技术>),在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根 ...

  4. Docker(十四)-Docker四种网络模式

    Docker 安装时会自动在 host 上创建三个网络,我们可用 docker network ls 命令查看: none模式,使用--net=none指定,该模式关闭了容器的网络功能. host模式 ...

  5. Docker笔记03-docker 网络模式

    docker网络模式分为5种 Nat (Network Address Translation) Host other container none overlay 第一种 Nat模式 docker的 ...

  6. Docker——四种网络模式

    docker run创建Docker容器时,可以用–net选项指定容器的网络模式,Docker有以下4种网络模式:  bridge模式:使用–net =bridge指定,默认设置:  host模式 ...

  7. docker基础_网络模式

    docker网络 网络模式: bridge:docker默认 自己创建会默认使用bridge模式 类似vmware中的NAT模式 其中192.168.1.203是本机在现实世界局域网的ip.172.1 ...

  8. docker四种网络模式

    1,host模式 启动容器时,添加参数--net=host 此模式和宿主机使用的是同1个ip,适合上网. 2,container模式 启动容器时,添加参数--net=container,docker ...

  9. Docker系列02—Docker 网络模式

    一.Docker的四种网络模式 1.Docker 的四种网络模式: Bridge container 桥接式网络模式 Host(open) container 开放式网络模式 Container(jo ...

  10. Docker的4种网络模式

    我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式: · host模式,使用--net=host指定. · container ...

随机推荐

  1. SQL Server AdventureWorks示例数据库

    SQL Server AdventureWorks2008R2 数据字典 AdventureWorks2008R2示例数据库下载 AdventureWorks2008R2数据字典(官网) Addres ...

  2. 前缀函数及 Knuth–Morris–Pratt 算法学习笔记

    \(\text{1 引言 Preface}\) 对于形如以下的问题: 给予一个模式串 \(T\) 和主串 \(S\),在主串中寻找 \(T\). 我们称之为字符串匹配. 很显然朴素算法时间复杂度是 \ ...

  3. java开发,json转list集合,原生实现

    java 是一门面象对象的语言,对象需要先定义,但是在外理网络请求时候会用到json 转成java 对象,虽然现代开发框架中也提供了很多工具和方法直接转换, 但是作为学习者了解 一下底层实现,更能灵活 ...

  4. Windows安装虚拟机软件-VirtualBox

    1.VirtualBox简介 VirtualBox号称是最强的开源免费虚拟机软件,它不仅具有丰富的特色,而且性能也很优异. 它简单易用,可虚拟的系统包括Windows.Mac OS X.Linux.O ...

  5. 3天搞定Linux,1天搞定Shell笔记

    Linux概述 Linux是一个操作系统OS 开源 MacOS基于Darwin,Darwin基于FreeBSD开发. Linux基于Minix(开发重写),Minix基于Unix开发. Linux一切 ...

  6. 【转载】人工智能CAE仿真分析技术

    原文: https://cloud.tencent.com/developer/news/628731 AI与CAE相结合 CAE的本质是对复杂工程问题通过合理简化建立数学模型,并根据输入求得输出.深 ...

  7. 读论文《IMPALA: Scalable Distributed Deep-RL with Importance Weighted Actor-Learner Architectures》——(续)实验部分

    论文地址: https://arxiv.org/pdf/1802.01561v2.pdf 论文<IMPALA: Scalable Distributed Deep-RL with Importa ...

  8. [rCore学习笔记 022]多道程序与分时任务

    写在前面 本随笔是非常菜的菜鸡写的.如有问题请及时提出. 可以联系:1160712160@qq.com GitHhub:https://github.com/WindDevil (目前啥也没有 思考 ...

  9. devtools工具遇到的坑

    下载devtools一定要下载5.1.1版本,其他版本要么就是下载依赖不行,要么就是打包不行,不清楚的同学会下载最新版,最新版的不能用,切记 地址放这里了: https://github.com/vu ...

  10. apisix-dashboard上添加自定义插件

    参考:https://overstarry.vip/posts/apisix如何添加自定义插件/ 首先,我们需要向自定义的插件user-remote-auth添加到apisix中,对这块不清楚的同学, ...