一、端口暴露

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. vscode 常用设置

    vscode 常用设置   by:授客 QQ:1033553122   版本 vscode Version: 1.33.1   1.   自动保存文件设置 文件编辑一秒钟过后自动保存 2.   黏贴后 ...

  2. 张高兴的 MicroPython 入门指南:(三)使用串口通信

    目录 什么是串口 使用方法 使用板载串口相互通信 硬件需求 电路 代码 使用板载的 USB 串口 参考 什么是串口 串口是串行接口的简称,这是一个非常大的概念,在嵌入式中串口通常指 UART(Univ ...

  3. 《最新出炉》系列入门篇-Python+Playwright自动化测试-54- 上传文件(input控件) - 上篇

    1.简介 在实际工作中,我们进行web自动化的时候,文件上传是很常见的操作,例如上传用户头像,上传身份证信息等.所以宏哥打算按上传文件的分类对其进行一下讲解和分享. 2.上传文件的API(input控 ...

  4. Python获取指定网段正在使用的IP

    Python获取指定网段正在使用的IP #!/usr/bin/env python # -*- coding: utf-8 -*- ''''' 使用方法样例 python test20.py 192. ...

  5. 【SpringBoot】09 日志集成

    原来日志还分抽象层和实现层... 抽象层被称为是日志门面,实现层被称为是日志实现 门面的有: - JCL[Jakarta Commons Logging]    远古门面 - SLF4J[Simple ...

  6. 树莓派3b+ 安装Ubuntu mate18.04系统 配置SSH 、 远程桌面realvnc

    Ubuntu mate  for  树莓派3b+ 系统下载: 下载地址: https://ubuntu-mate.org/download/ 这里用32位系统:(64位也可以的,虽然还是实验阶段的,不 ...

  7. 【转载】 Docker-关于docker cpu的限制后,实际效果的研究

    原文地址: https://zhuanlan.zhihu.com/p/46275332 ================================================== 思考:我们 ...

  8. Ubuntu18.04 系统环境下 vscode中忽略pylint某些错误或警告

    相关: ubuntu18.04系统环境下使用vs code安装pylint检查python的代码错误 ====================================== 假设已经在前文(ht ...

  9. ubuntu环境下boost库的安装——Could NOT find Boost (missing: Boost_INCLUDE_DIR program_options) (Required is at least version "1.49.0")

    在Ubuntu环境下使用cmake编译软件,报错,提示信息: Could NOT find Boost (missing: Boost_INCLUDE_DIR program_options) (Re ...

  10. 多线程之深入理解park与unpark

    1.背景 面试官问,如何暂停一个线程勒..... 说说你对park的理解....... 2.代码 package com.ldp.demo01; import com.common.MyThreadU ...