78

我想创建一个能够在不同服务器上运行的docker-compose文件。

为此,我必须能够在docker-compose.yml的多个位置指定服务器的主机 IP 或主机名(所有容器都在其中运行) 。

例如,对于一个领事容器,我想定义其他领事容器如何找到服务器。

consul:
  image: progrium/consul
  command: -server -advertise 192.168.1.125 -bootstrap

我显然不想硬编码 192.168.1.125 。

我可以使用 env_file :指定主机名或 ip 并在每台服务器上采用它,因此我将这些信息放在一个地方并在 docker-compose.yml 中使用它。但这只能用于指定环境变量,不能用于广告参数。

有更好的解决方案吗?

4

7 回答 7

22

docker-compose 允许使用运行 compose 命令的环境中的环境变量。

请参阅https://docs.docker.com/compose/compose-file/#variable-substitution上的文档

假设您可以创建一个包装脚本,就像@balver 建议的那样,您可以设置一个名为的环境变量EXTERNAL_IP,该变量将包含$(docker-machine ip).

例子:

#!/bin/sh
export EXTERNAL_IP=$(docker-machine ip)
exec docker-compose $@

# docker-compose.yml
version: "2"
services:
  consul:
    image: consul
    environment:
      - "EXTERNAL_IP=${EXTERNAL_IP}"
    command: agent -server -advertise ${EXTERNAL_IP} -bootstrap

不幸的是,如果您使用随机端口分配,则无法添加EXTERNAL_PORT,因此端口必须静态链接。

PS:在 HashiCorp Nomad 中默认启用了非常相似的功能,还包括映射端口。文档:https ://www.nomadproject.io/docs/jobspec/interpreted.html#interpreted_env_vars

于 2016-06-07T13:06:09.493 回答
20

我使用了似乎是静态的 docker 内部网络 IP:172.17.0.1

于 2016-09-02T10:51:45.793 回答
17

有更好的解决方案吗?

绝对地!容器之间的通信根本不需要主机 ip。如果您在文件中使用link容器docker-compose.yaml,您将可以访问许多环境变量,您可以使用这些变量来发现服务的 IP 地址。

例如,考虑一个带有两个容器的 docker-compose 配置:一个使用consul,另一个运行一些需要与 consul 对话的服务。

consul:
  image: progrium/consul
  command: -server -bootstrap
webserver:
  image: larsks/mini-httpd
  links:
    - consul

首先,从consuljust开始-server -bootstrapconsul找出它自己的广告地址,例如:

consul_1    | ==> Consul agent running!
consul_1    |          Node name: 'f39ba7ef38ef'
consul_1    |         Datacenter: 'dc1'
consul_1    |             Server: true (bootstrap: true)
consul_1    |        Client Addr: 0.0.0.0 (HTTP: 8500, HTTPS: -1, DNS: 53, RPC: 8400)
consul_1    |       Cluster Addr: 172.17.0.4 (LAN: 8301, WAN: 8302)
consul_1    |     Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
consul_1    |              Atlas: <disabled>

webserver容器中,我们发现以下可用于 pid 1 的环境变量:

CONSUL_PORT=udp://172.17.0.4:53
CONSUL_PORT_8300_TCP_START=tcp://172.17.0.4:8300
CONSUL_PORT_8300_TCP_ADDR=172.17.0.4
CONSUL_PORT_8300_TCP_PROTO=tcp
CONSUL_PORT_8300_TCP_PORT_START=8300
CONSUL_PORT_8300_UDP_END=udp://172.17.0.4:8302
CONSUL_PORT_8300_UDP_PORT_END=8302
CONSUL_PORT_53_UDP=udp://172.17.0.4:53
CONSUL_PORT_53_UDP_ADDR=172.17.0.4
CONSUL_PORT_53_UDP_PORT=53
CONSUL_PORT_53_UDP_PROTO=udp
CONSUL_PORT_8300_TCP=tcp://172.17.0.4:8300
CONSUL_PORT_8300_TCP_PORT=8300
CONSUL_PORT_8301_TCP=tcp://172.17.0.4:8301
CONSUL_PORT_8301_TCP_ADDR=172.17.0.4
CONSUL_PORT_8301_TCP_PORT=8301
CONSUL_PORT_8301_TCP_PROTO=tcp
CONSUL_PORT_8301_UDP=udp://172.17.0.4:8301
CONSUL_PORT_8301_UDP_ADDR=172.17.0.4
CONSUL_PORT_8301_UDP_PORT=8301
CONSUL_PORT_8301_UDP_PROTO=udp
CONSUL_PORT_8302_TCP=tcp://172.17.0.4:8302
CONSUL_PORT_8302_TCP_ADDR=172.17.0.4
CONSUL_PORT_8302_TCP_PORT=8302
CONSUL_PORT_8302_TCP_PROTO=tcp
CONSUL_PORT_8302_UDP=udp://172.17.0.4:8302
CONSUL_PORT_8302_UDP_ADDR=172.17.0.4
CONSUL_PORT_8302_UDP_PORT=8302
CONSUL_PORT_8302_UDP_PROTO=udp
CONSUL_PORT_8400_TCP=tcp://172.17.0.4:8400
CONSUL_PORT_8400_TCP_ADDR=172.17.0.4
CONSUL_PORT_8400_TCP_PORT=8400
CONSUL_PORT_8400_TCP_PROTO=tcp
CONSUL_PORT_8500_TCP=tcp://172.17.0.4:8500
CONSUL_PORT_8500_TCP_ADDR=172.17.0.4
CONSUL_PORT_8500_TCP_PORT=8500
CONSUL_PORT_8500_TCP_PROTO=tcp

EXPOSE图像的每个端口d都有一组变量consul 。例如,在第二张图片中,我们可以通过连接到 consul REST API 进行交互:

http://${CONSUL_PORT_8500_TCP_ADDR}:8500/
于 2015-03-18T01:07:04.210 回答
15

使用新版本的 Docker Compose ( 1.4.0 ),您应该能够执行以下操作:

码头工人-compose.yml

consul:
  image: progrium/consul
  command: -server -advertise HOSTIP -bootstrap

重击

$ sed -e "s/HOSTIP/${HOSTIP}/g" docker-compose.yml | docker-compose --file - up

这要归功于新功能:

  • Compose 现在可以通过将 - 指定为文件名来从标准输入而不是从文件中读取 YAML 配置。这使得动态生成配置变得更加容易:

    $ echo 'redis: {"image": "redis"}' | docker-compose --file - up
    
于 2015-08-14T13:20:20.793 回答
5

正如之前的解决方案中所建议的,环境变量是由 Docker 在链接容器时创建的。但是如果容器重新启动,环境变量不会自动更新。因此,不建议在生产中使用环境变量。

Docker 除了创建环境变量外,还会更新 /etc/hosts 文件中的主机条目。事实上,Docker 文档建议使用来自 etc/hosts 的主机条目而不是环境变量。

参考:https ://docs.docker.com/userguide/dockerlinks/

与 /etc/hosts 文件中的主机条目不同,如果源容器重新启动,存储在环境变量中的 IP 地址不会自动更新。我们建议使用 /etc/hosts 中的主机条目来解析链接容器的 IP 地址。

于 2015-04-03T08:56:47.423 回答
2

extra_hosts工作,它是硬编码的,docker-compose.yml但对于我当前的静态设置,此刻这就是我所需要的。

version: '3'
services:
  my_service:
    container_name: my-service
    image: my-service:latest
    extra_hosts:
      - "myhostname:192.168.0.x"

    ...

    networks:
      - host
networks:
  host:
于 2019-11-21T08:42:13.407 回答
1

创建一个脚本以在每次启动时在环境变量中设置您的主机 IP。

sudo vi /etc/profile.d/docker-external-ip.sh

然后复制这段代码:

export EXTERNAL_IP=$(hostname -I | awk '{print $1}')

现在您可以在 docker-compose.yml 文件中使用它:

version: '3'
services:
  my_service:
    container_name: my-service
    image: my-service:latest
    environment:
    - EXTERNAL_IP=${EXTERNAL_IP}
    extra_hosts:
    - my.external-server.net:${EXTERNAL_IP}

    ...
  • environment --> 在你的 docker 容器中设置为系统环境变量
  • extra_hosts --> 将这些主机添加到您的 docker 容器中
于 2021-02-25T12:28:00.933 回答