docker 容器 IP 会在重启时发生变化吗?

do docker container IPs change on restart?

我是 docker 的新手,我一直在 docker 在一台服务器上处理我的所有应用程序。到目前为止,一切都很好并且可以正常工作。但是,我不明白一件事。我正在为所有内容使用 docker-compose(我还没有为我的项目创建 dockerfile)并且 docker-compose 中有这个 ports 属性。如果我这样写:

ports:
    8085:80

它将监听 0.0.0.0:8085,这意味着外部世界可以访问我的服务器。经过一些讨论和 google-ing,我发现我可以在我的 docker 桥接网络中获取一个 IP 地址并轻松地进行端口映射:

ports:
    172.17.0.1:8085:80

这将仅在 172.17.0.1:8085 上侦听,这很棒,因为它仅在内部侦听并且我的 nginx 将流量代理到必要的端口。 (例如 proxy_pass http://172.17.0.1:8085)。在更多地了解 docker 并了解它们的工作原理后,我意识到所有这些容器都有自己的 IP 地址,并且端口只暴露给这些地址。例如,我的一个 "web" 容器的 IPv4 地址为 172.17.0.10 并且端口 80 被暴露。如果我对其中一个容器执行 docker inspect,我将看到该容器的 IP 地址。

现在,我想在我的 nginx 中使用这些 IP 地址。我想 http://172.17.0.10 而不是 proxy_pass http://172.17.0.1:8085。我个人认为这是一个非常优雅的界面,但有一件事让我担心。如果我重新启动我的机器会发生什么?所有容器将以某种顺序启动。如果我有 5 个 Web 容器并且它们以随机顺序启动,我可以确定这些容器的 IP 相同吗?或者他们会改变吗?我应该总是在 docker-compose 中使用 ports 以供 nginx 使用吗?如果是,我如何让每个容器拥有不同的 IP,而不是具有相同 IP 的不同端口?如果我创建另一个 docker 网络接口(假设在子网 172.17.1.0 中),并从该接口分配不同的 IP 到暴露的 "public" 端口,是否可以?我的意思是基本上在一个容器中使用 172.17.1.1:80:80,在另一个容器中使用 172.17.1.2:80:80,等等。

不是 docker 网络领域的专家,但我会尽力回答您提出的问题。

问: 如果我重新启动机器会怎样?所有容器将按某种顺序启动。
A: 除非你使用linksdepends_on关键字,否则无法保证启动顺序。

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

他们在

运行
  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分配是基于先到先得的原则。如果您没有指定启动容器的顺序,我认为容器的 ip 可能不同。真的要看谁先跑了。

问: 我是否应该始终使用 docker-compose 中的端口供 nginx 使用?
A: 是的,如果你想将 nginx 实例的端口转发到外部世界。否则没有人能够访问该 Web 服务器。例如。公开端口 443HTTPs 流量通过。

问:如何让每个容器拥有不同的 IP,而不是拥有相同 IP 的不同端口?
A: 我不知道这是否可行,但在为您对 docker-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 配置中,它们将自动成为同一内部网络的一部分,您可以简单地使用服务名称作为主机名。

例如,如果您的网络应用名为 php,您的 nginx 代理配置将类似于:

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

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