如何在没有环境变量的情况下从该主机上的 docker 容器中获取 docker 主机的主机名

How to get the hostname of the docker host from inside a docker container on that host without env vars

除了使用环境变量之外,还有什么方法可以从主机上的容器 运行 中获取 docker 主机的主机名? 我知道我可以在创建容器时将主机名作为环境变量传递给容器。我想知道如何在 运行 时查找它。

foo.example.com (docker host)
  bar (docker container)

docker主机foo.example.com中的容器bar运行是否有办法获得"foo.example.com"?

编辑以添加用例:

容器将为服务发现创建一个 SRV 记录

_service._proto.name. TTL class SRV priority weight port target.
-----------------------------------------------------------------
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo.example.com.

其中 20003 是 docker 主机上动态分配的端口,用于侦听 bar 中某个固定端口的服务(docker 处理从主机端口到容器端口的映射)。

我的容器将 运行 进行健康检查,以确保它已成功创建该 SRV 记录,因为其他 docker 主机上的许多其他 bar 容器也会创建自己的 SRV 记录。

_service._proto.name. TTL class SRV priority weight port target.
-----------------------------------------------------------------
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo.example.com. <--
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo2.example.com.
_bar._http.example.com 60 IN SRV 5000 5000 20003 foo3.example.com.

运行状况检查将遍历 SRV 记录以查找上面的第一个记录,因此需要知道它的主机名。

一边

我正在使用 Helios and just found out it adds an env var for me,我可以从中获取主机名。但我只是好奇,如果我在没有 Helios 的情况下使用 docker。

您可以将主机名作为环境变量传入。您还可以挂载 /etc,这样您就可以 cat /etc/hostname。但我同意 Vitaly 的观点,这不是容器 IMO 的预期用例。

您可以轻松地将其作为环境变量传递

docker run .. -e HOST_HOSTNAME=`hostname` ..

使用

-e HOST_HOSTNAME=`hostname`

将调用主机名并将其return用作环境变量HOST_HOSTNAME,当然您可以根据需要自定义密钥。

请注意,这适用于 bash shell,如果您使用不同的 shell,您可能需要查看 "backtick" 的替代方案,例如 fish shell 备选方案是

docker run .. -e HOST_HOSTNAME=(hostname) ..

另一个对我有用的选项是将主机的网络名称空间绑定到 docker。

通过添加:

docker run --net host

我添加这个是因为它没有在任何其他答案中提到。您可以使用 -h 指令在 运行 时间给容器一个特定的主机名。

docker run -h=my.docker.container.example.com ubuntu:latest

您可以使用反引号(或您 shell 使用的任何等效物)将 hosthame 的输出放入 -h 参数。

docker run -h=`hostname` ubuntu:latest

需要注意的是,hostname 的值将从您 运行 命令所在的主机中获取,因此如果您想要 运行 正在 [=] 的虚拟机的主机名18=] 容器然后使用主机名作为参数可能不正确,如果您使用主机在虚拟机上执行 docker 命令。

我认为我遇到同样问题的原因是 bug in the latest Docker for Mac beta,但隐藏在评论中我能够找到适合我和我的团队的解决方案。我们正在将其用于本地开发,我们需要我们的容器化服务在我们努力替换它时与单体通信。这可能不是一个可行的生产解决方案。

在主机上,为环回接口指定一个已知可用 IP 地址的别名:

$ sudo ifconfig lo0 alias 10.200.10.1/24

然后将该 IP 和主机名添加到您的 docker 配置中。就我而言,我正在使用 docker-compose,所以我将其添加到我的 docker-compose.yml:

extra_hosts:
# configure your host to alias 10.200.10.1 to the loopback interface:
#       sudo ifconfig lo0 alias 10.200.10.1/24
- "relevant_hostname:10.200.10.1"

然后我通过附加到 bash 会话并使用 wget 从主机的 Web 请求页面来验证所需的主机服务(Web 服务器)在容器内可用服务器:

$ docker exec -it container_name /bin/bash
$ wget relevant_hostname/index.html
$ cat index.html

我知道这是一个老问题,但我也需要这个解决方案,我想出了另一个解决方案。

我使用 entrypoint.sh 来执行以下行,并为该实例定义一个具有实际主机名的变量:

HOST=`hostname --fqdn`

然后,我在入口点脚本中使用了它:

echo "Value: $HOST"

希望对您有所帮助

您可以像这样将其作为环境变量传递。一般Node就是它所在运行所在的主机。主机名默认为节点创建时的主机名。

docker service create -e 'FOO={{.Node.Hostname}}' nginx  

然后你可以docker ps获取进程ID并查看env

$ docker exec -it c81640b6d1f1 env                                                                                                                                    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=c81640b6d1f1
TERM=xterm
FOO=docker-desktop
NGINX_VERSION=1.17.4
NJS_VERSION=0.3.5
PKG_RELEASE=1~buster
HOME=/root

使用 metricbeats 的一个例子,所以你知道哪个节点有系统问题,我在 https://github.com/trajano/elk-swarm:

  metricbeat:
    image: docker.elastic.co/beats/metricbeat:7.4.0
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /sys/fs/cgroup:/hostfs/sys/fs/cgroup:ro
      - /proc:/hostfs/proc:ro
      - /:/hostfs:ro
    user: root
    hostname: "{{.Node.Hostname}}"
    command:
      - -E
      - |
        metricbeat.modules=[
          {
            module:docker,
            hosts:[unix:///var/run/docker.sock],
            period:10s,
            enabled:true
          }
        ] 
      - -E
      - processors={1:{add_docker_metadata:{host:unix:///var/run/docker.sock}}} 
      - -E
      - output.elasticsearch.enabled=false
      - -E
      - output.logstash.enabled=true
      - -E
      - output.logstash.hosts=["logstash:5044"]
    deploy:
      mode: global

我运行

docker info | grep Name: | xargs | cut -d' ' -f2

在我的容器里。

 HOSTIP=`ip -4 addr show scope global dev eth0 | grep inet | awk '{print }' | cut -d / -f 1 | sed -n 1p`
 docker run  --add-host=myhost:${HOSTIP} --rm -it debian

现在您可以使用别名“myhost”访问主机了

第一行在 cygwin 上不会 运行,但您可以想出一些其他方法来使用 ipconfig 获取本地 IP 地址。