docker集装箱的IP在重新启动时更改吗?

我是docker的新手,我一直在我的应用程序docker化在一个单一的服务器。 到目前为止,一切都很好,工作。 但是,我不明白一件事。 我正在使用docker-compose(我还没有为我的项目创builddockerfile),并且在docker-compose中有这个ports属性。 如果我写这样的东西:

 ports: 8085:80 

它将听取0.0.0.0:8085,这意味着外面的世界已经访问我的服务器。 经过一些讨论和谷歌,我发现我可以在我的docker桥networking中的IP地址,并轻松地做端口映射:

 ports: 172.17.0.1:8085:80 

这将只听172.17.0.1:8085,这是伟大的,因为它只是在内部监听,我的nginx代理的stream量到必要的端口。 (例如, proxy_pass http://172.17.0.1:8085 )。 在了解了更多关于docker的信息并了解其工作原理后,我意识到所有这些容器都有自己的IP地址,只有这些地址才暴露出来。 例如,我的一个“web”容器的IPv4地址是172.17.0.10,端口80是公开的。 如果我对这些容器中的一个执行docker inspect ,我会看到容器的IP地址。

现在,我想在我的nginx中使用这些IP地址。 而不是proxy_pass http://172.17.0.1:8085 ,我想要做http://172.17.0.10 。 我个人认为这是一个非常优雅的界面,但有一件事情关注我。 如果我重新启动机器会发生什么? 所有的容器都会以某种顺序启动。 如果我有5个Web容器,并且它们以随机顺序启动,我可以确定这些容器的IP是相同的吗? 或者他们会改变? 我应该总是使用docker-compose中的ports来供nginx使用吗? 如果是的话,我怎样才能有不同的IP地址,而不是不同的IP地址? 如果我创build另一个dockernetworking接口(比如在子网172.17.1.0中),是否可以,并将该接口的不同IP分配给公开的“公共”端口? 我的意思是基本上在一个容器中使用172.17.1.1:80:80在另一个容器中使用172.17.1.1:80:80

不是码头网络领域的专家,但我会尽我所能来回答你在那里的问题。

问:如果我重新启动机器会发生什么情况? 所有的容器都会以某种顺序启动。
答:除非您使用linksdepends_on关键字,否则您不能保证启动顺序。

问:如果我有5个Web容器,并且它们以随机顺序启动,我可以确定这些容器的IP是相同的吗?
答:我通过记下我现有的2个容器(postgresDB和influxDB)的ipaddresses,在我的机器上做了一个小实验。

他们正在运行

  1. Postgres:172.17.0.2
  2. InfluxDB:172.17.0.3

关闭并重新启动。 可能是由于他们这次启动了相同的命令,ip地址似乎已经被保留了。 增加了depends_on关键字来强制InfluxDB容器在Postgres之前先启动,现在两个容器的IP地址都是;

  1. Postgres:172.17.0.3
  2. InfluxDB:172.17.0.2

我认为知识产权是以先到先得的方式分配的。 如果你没有指定一个启动容器的命令,我认为容器的IP可能不同。 真的取决于谁先跑。

问:我应该总是使用docker-compose中的port来供nginx使用吗?
答:是的,如果你想将一个nginx实例的端口移植到外部世界。 否则,没有人能够击中该Web服务器。 例如公开端口443HTTPs流量通过。

问:如何为每个容器分配不同的IP,而不是具有相同IP的不同端口?
答:我不知道这是否可行,但是在对ipam -compose文档进行一些研究之后,通过使用ipam关键字似乎是可能的。

看到:
https://docs.docker.com/compose/compose-file/#/ipam

这对我来说看起来很可怕,所以我为自己的项目所做的是使用service_name

例:

 container_bbb: image: banana my_nginx: image: apple environment: - MOUNT_SRC0=http://container_bbb:80 - MOUNT_DEST0=/ links: - container_bbb 

对于my_nginx容器中的这个实例,服务名称container_bbb将被解析为该容器的主机名。 然后我将有一个python脚本,它将在容器的入口脚本区域使用这些信息动态生成ngix配置。

听起来有点矫枉过正,但是这让我更多的控制了我想用我的nginx做什么。

所以在我的/etc/nginx/conf.d/default-locations/配置将是类似的;

 location /container_bbb/ { proxy_pass http://container_bbb:3000/; } 

注意:我正在使用这个nginx服务器实例作为反向代理服务器。

我想我在这里想说的是,你可以基本上使用主机名而不是IP地址。 要到达隔壁的容器,您可以通过http://CONTAINER_SERVICE_NAME:PORT

你不能依靠容器的IP地址。 如果所有的服务都在同一个docker-compose配置中,它们将自动成为同一个内部网络的一部分,你可以简单地使用服务名称作为主机名。

例如,如果您的Web应用程序被命名为php ,则您的nginx代理配置将如下所示:

 location / { proxy_pass http://php; proxy_set_header Host $host; proxy_redirect off; } 

(另外请注意,您可能需要启用防火墙,以防万一任何端口映射泄漏到主机的公共IP地址。)