文档章节

[转载] Docker网络原则入门:EXPOSE,-p,-P,-link

劲风online
 劲风online
发布于 2015/10/27 19:27
字数 2295
阅读 3633
收藏 6
点赞 0
评论 0

标签:

原文: http://dockone.io/article/455

如果你已经构建了一些多容器的应用程序,那么肯定需要定义一些网络规则来设置容器间的通信。有多种方式可以实现:可以通过--expose参数在运行时暴露端口,或者在Dockerfile里使用EXPOSE指令。还可以在Docker run的时候通过-p或者-P参数来发布端口。或者通过--link链接容器。虽然这些方式几乎都能达到一样的结果,但是它们还是有细微区别。那么到底应该使用哪一种呢?

TL;DR

使用-p或者-P来创建特定端口绑定规则最为可靠,EXPOSE可以看做是容器文档化的方式,谨慎使用--link的方式。

在比较这些不同方式之前,我们先分别了解细节。

通过EXPOSE或者-expose暴露端口

有两种方式可以用来暴露端口:要么用EXPOSE指令在Dockerfile里定义,要么在docker run时指定--expose=1234。这两种方式作用相同,但是,--expose可以接受端口范围作为参数,比如 --expose=2000-3000。但是,EXPOSE--expose都不依赖于宿主机器。默认状态下,这些规则并不会使这些端口可以通过宿主机来访问。

基于EXPOSE指令的上述限制,Dockerfile的作者一般在包含EXPOSE规则时都只将其作为哪个端口提供哪个服务的提示。使用时,还要依赖于容器的操作人员进一步指定网络规则。和-P参数联合使用的情况,下文会进一步阐述。不过通过EXPOSE命令文档化端口的方式十分有用。

本质上说,EXPOSE或者--expose只是为其他命令提供所需信息的元数据,或者只是告诉容器操作人员有哪些已知选择。

实际上,在运行时暴露端口和通过Dockerfile的指令暴露端口,这两者没什么区别。在这两种方式启动的容器里,通过docker inspect $container_id | $container_name查看到的网络配置是一样的:

"NetworkSettings": {"PortMapping": null,"Ports": {    "1234/tcp": null}},"Config": {"ExposedPorts": {    "1234/tcp": {}}}


可以看到端口被标示成已暴露,但是没有定义任何映射。注意这一点,因为我们查看的是发布端口。

ProTip:使用运行时标志--expose是附加的,因此会在Dockerfile的EXPOSE指令定义的端口之外暴露添加的端口。

使用-p发布特定端口

可以使用-p参数显式将一个或者一组端口从容器里绑定到宿主机上,而不仅仅是提供一个端口。注意这里是小写的p,不是大写。因为该配置依赖于宿主机器,所以Dockerfile里没有对应的指令,这是运行时才可用的配置。-p参数有几种不同的格式:

ip:hostPort:containerPort| ip::containerPort | hostPort:containerPort | containerPort


实际中,可以忽略ip或者hostPort,但是必须要指定需要暴露的containerPort。另外,所有这些发布的规则都默认为tcp。如果需要udp,需要在最后加以指定,比如-1234:1234/udp。如果只是用命令docker run -8080:3000 my-image运行一个简单的应用程序,那么容器里运行在3000端口的服务在宿主机的8080端口也就可用了。端口不需要一样,但是在多个容器都暴露端口时,必须注意避免端口冲突。

避免冲突的最佳方法是让Docker自己分配hostPort。在上述例子里,可以选择docker run -3000 my_image来运行容器,而不是显式指定宿主机端口。这时,Docker会帮助选择一个宿主机端口。运行命令docker port $container_id | $container_name可以查看Docker选出的端口号。除了端口号,该命令只能显示容器运行时端口绑定信息。还可以通过在容器上运行docker inspect查看详细的网络信息,在定义了端口映射时,这样的信息就很有用。该信息在Config、HostConfig和NetworkSettings部分。我们查看这些信息来对比不同方式搭建的容器间的网络区别。

ProTip:可以用-p参数定义任意数量的端口映射。

-expose/EXPOSE和-p对比

为了更好得理解两者之间的区别,我们使用不同的端口设置来运行容器。

运行一个很简单的应用程序,会在curl它的时候打印‘hello world‘。称这个镜像为no-exposed-ports:

FROM ubuntu:trusty
MAINTAINER Laura Frank <laura.frank@centurylink.com>CMD while true; do echo ‘hello world‘ | nc -l -p 8888; done


实验时注意使用的是Docker主机,而不是boot2docker。如果使用的是boot2docker,运行本文示例命令前先运行boot2docker ssh

注意,我们使用-d参数运行该容器,因此容器一直在后台运行。(端口映射规则只适用于运行着的容器):

$ docker run -d --name no-exposed-ports no-exposed-ports
e18a76da06b3af7708792765745466ed485a69afaedfd7e561cf3645d1aa7149


这儿没有太多的信息,只是回显了容器的ID,提示服务已经成功启动。和预期结果一样,运行docker port no-exposed-portsdocker inspect no-exposed-ports时没显示什么信息,因为我们既没有定义端口映射规则也没有发布任何端口。

因此,如果我们发布一个端口会发生什么呢,-p参数和EXPOSE到底有什么区别呢?

还是使用上文的no-exposed-ports镜像,在运行时添加-p参数,但是不添加任何expose规则。在config.ExposedPorts里重新查看--expose参数或者EXPOSE指令的结果。

$ docker run -d --name no-exposed-ports-with-p-flag -p 8888:8888 no-exposed-ports
c876e590cfafa734f42a42872881e68479387dc2039b55bceba3a11afd8f17ca
$ docker port no-exposed-ports-with-p-flag8888/tcp -> 0.0.0.0:8888


太棒了!我们可以看到可用端口。注意默认这是tcp。我们到网络设置里看看还有什么信息:

"Config": {[...]"ExposedPorts": {    "8888/tcp": {}}},"HostConfig": {[...]"PortBindings": {    "8888/tcp": [        {            "HostIp": "",            "HostPort": "8888"        }    ]}},"NetworkSettings": {[...]"Ports": {    "8888/tcp": [        {            "HostIp": "0.0.0.0",            "HostPort": "8888"        }    ]}}


注意”Config“部分的暴露端口字段。这和我们使用EXPOSE或者--expose暴露的端口是一致的。Docker会隐式暴露已经发布的端口。已暴露端口和已发布端口的区别在于已发布端口在宿主机上可用,而且我们可以在“HostConfig”和“NetworkSettings”两个部分都能看到已发布端口的信息。

所有发布(-p或者-P)的端口都暴露了,但是并不是所有暴露(EXPOSE--expose)的端口都会发布。

使用-P和EXPOSE发布端口

因为EXPOSE通常只是作为记录机制,也就是告诉用户哪些端口会提供服务,Docker可以很容易地把Dockerfile里的EXPOSE指令转换成特定的端口绑定规则。只需要在运行时加上-P参数,Docker会自动为用户创建端口映射规则,并且帮助避免端口映射的冲突。

添加如下行到上文使用的Web应用Dockerfile里:

EXPOSE 1000EXPOSE 2000EXPOSE 3000


构建镜像,命名为exposed-ports。

docker build -t exposed-ports .


再次用-P参数运行,但是不传入任何特定的-p规则。可以看到Docker会将EXPOSE指令相关的每个端口映射到宿主机的端口上:

$ docker run -d -P --name exposed-ports-in-dockerfile exposed-ports63264dae9db85c5d667a37dac77e0da7c8d2d699f49b69ba992485242160ad3a$ docker port exposed-ports-in-dockerfile1000/tcp -> 0.0.0.0:491562000/tcp -> 0.0.0.0:491573000/tcp -> 0.0.0.0:49158


很方便,不是么?

--link怎么样呢?

你可能在多容器应用程序里使用过运行时参数 --link namealias来设定容器间关系。虽然--link非常易于使用,几乎能提供和端口映射规则和环境变量相同的功能。但是最好将--link当做服务发现的机制,而不是网络流量的门户。

--link参数唯一多做的事情是会使用源容器的主机名和容器ID来更新新建目标容器(使用--link参数创建的容器)的/etc/hosts文件。

当使用--link参数时,Docker提供了一系列标准的环境变量,如果想知道细节的话可以查看相应文档

虽然--link对于需要隔离域的小型项目非常有用,它的功能更像服务发现的工具。如果项目中使用了编排服务,比如Kubernetes或者Fleet,很可能就会使用别的服务发现工具来管理关系。这些编排服务可能会不管理Docker的链接,而是管理服务发现工具里包含的所有服务,在Panamax项目里使用的很多远程部署适配器正是做这个的。

找到平衡

哪一种网络选择更为适合,这取决于谁(或者哪个容器)使用Docker运行的服务。需要注意的是一旦镜像发布到Docker Hub之后,你无法知道其他人如何使用该镜像,因此要尽可能让镜像更加灵活。如果你只是从Docker Hub里取得镜像,使用-P参数运行容器是最方便迅速的方式,来基于作者的建议创建端口映射规则。记住每一个发布的端口都是暴露端口,但是反过来是不对的。

快速参考

技术分享

本文转载自:http://www.mamicode.com/info-detail-891635.html

共有 人打赏支持
劲风online
粉丝 5
博文 75
码字总数 41688
作品 0
海淀
程序员
docker EXPOSE vs publish

Docker里面expose和publish(run -p)的区别 这里主要记录的是我最近使用docker发现的一个小小的疑惑。总结起来就是: docker里,命令行启动时候docker run -p暴露接口和dockerfile里expos...

来福马斯特 ⋅ 2017/11/09 ⋅ 0

Docker快速搭建个人博客网站(wordpress+mysql)

声明:原创文章,转载请注明出处。http://www.jianshu.com/u/e02df63eaa87 1、基本知识 本着“容器只干一件事情”的原则,本文会将出现两个容器,一个Wordpress的网站程序的容器,另一个则是...

唐影若凡 ⋅ 2017/06/26 ⋅ 0

用Docker部署一个自己的可视化爬虫系统

Docker作为一种流行的容器技术,笔者也来玩玩,正好最近在开发一个可视化爬虫系统,Alpha版完成需要部署到服务器上,但是这个系统设计到的组建有点多,包括了Python3、Django、Pyspider、MyS...

Kanonpy ⋅ 2016/05/11 ⋅ 1

centos 基础性命令

docker 使用入门 docker 启动快的原因: 因为Container技术采取共享Host OS的作法,而不需在每一个Container内执行Guest OS,因此建立Container不需要等待操作系统开机时间,不用1分钟或几秒...

疯code ⋅ 2016/07/19 ⋅ 0

Docker启动容器时的port公开方式,破除一些含糊的地方

以前就好奇docker run时的port公开方式-p 8080:8080和--expose(或者Dockerfile里的EXPOSE)的区别, 当时相信了stackoverflow上高手的回答Difference between "expose" and "publish" in dock...

Q_J ⋅ 2016/07/08 ⋅ 0

Docker从入门到实践笔记(二)

挂载一个主机目录作为数据卷 使用-v标记也可以指定挂载一个本地主机的目录到容器中去。 $ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py 上面...

壬癸甲乙 ⋅ 2014/12/08 ⋅ 0

【4】Linking Containers Together

//网络端口映射 //-P随机映射到主机的49153~49155端口 $ docker run -d -P training/webapp python app.py //将镜像的5000端口映射到主机的5000端口 $ docker run -d -p 127.0.0.1::5000 t...

Sean-x ⋅ 2016/02/23 ⋅ 0

docker 容器的网络配置

Docker 中的网络功能介绍 默认情况下,容器可以建立到外部网络的连接,但是外部网络无法连接到容器。 Docker 允许通过外部访问容器或容器互联的方式来提供网络服务 外部访问容器: 容器中可以...

三极行者 ⋅ 2017/03/16 ⋅ 0

Docker----网络部分

项目概要: Docker网络通信部分 项目目的: 一:使用带有httpd应用的镜像创建一个容器,使用外网进行访问网站验证。 二:Docker 四种网络模式介绍 项目内容: 创建容器的时候可以使用带有-p或...

期待有一天 ⋅ 2017/08/04 ⋅ 0

Docker系列教程21-Docker Compose快速入门

原文:,转载请注明出处。 本节我们来探讨Compose使用的基本步骤,并编写一个简单示例快速入门。 基本步骤 使用Compose大致有三个步骤: 使用Dockerfile(或其他方式)定义应用程序环境,以便...

EACDY ⋅ 05/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 今天 ⋅ 0

JavaScript零基础入门——(十一)JavaScript的DOM操作

JavaScript零基础入门——(十一)JavaScript的DOM操作 大家好,欢迎回到我们的JavaScript零基础入门。最近有些同学问我说,我讲的的比书上的精简不少。其实呢,我主要讲的是我在开发中经常会...

JandenMa ⋅ 今天 ⋅ 0

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 今天 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 今天 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 今天 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 今天 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部