【问题标题】:How to get the hostname of the docker host from inside a docker container on that host without env vars如何在没有环境变量的情况下从该主机上的 docker 容器内部获取 docker 主机的主机名
【发布时间】:2015-04-22 21:10:46
【问题描述】:

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

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

有没有办法让容器 bar 在 docker 主机 foo.example.com 中运行以获取“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,只是发现它添加了一个env var for me,我可以从中获取主机名。但我只是好奇我在没有 Helios 的情况下使用 docker。

【问题讨论】:

  • 能否请您澄清一下,为什么需要此功能?
  • 如果你能解释你的用例,也许有更好的方法来解决你的问题?
  • @VitalyIsaev 添加了用例
  • 另一个出现这种情况的用例:如果您想使用 Docker 将 Erlang 部署容器化,但让 docker 容器内部的行为像主机一样对外部世界起作用。在这种情况下,您希望 erlang 节点具有与主机匹配的节点名。
  • 不幸的是 best answer 被删除了...只需使用 host.docker.internal

标签: docker


【解决方案1】:

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

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

使用

-e HOST_HOSTNAME=`hostname`

将调用主机名并将其返回作为名为@9​​87654323@的环境变量,当然您可以根据需要自定义密钥。

请注意,这适用于 bash shell,如果您使用不同的 shell,您可能需要查看“反引号”的替代方案,例如 fish shell 替代方案将是

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

【讨论】:

  • 我想知道是否有办法在不使用环境变量的情况下做到这一点。
  • 不幸的是,环境变量方法在使用带有docker-compose.env 文件时不起作用,但您可以在environment: 部分中使用$HOSTNAME
【解决方案2】:

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

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

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

docker run -h=`hostname` ubuntu:latest

有一个警告,主机名的值将从您运行命令的主机中获取,因此如果您想要运行 docker 容器的虚拟机的主机名,那么使用主机名作为参数可能不正确您正在使用主机在虚拟机上执行 docker 命令。

【讨论】:

  • 这是最好的答案,因为它会修改uname系统调用的输出。这样,它将与hostname 程序或其他C 编写的程序(例如Python 的socket.gethostname())一起使用。更改HOSTNAME 环境变量或将/etc/hostname 挂载到容器不会这样做。
【解决方案3】:

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

【讨论】:

  • 诸如“很难想象你为什么想要这个”之类的评论是无益且粗鲁的。当然,从一个绿色字段开始,这个请求不适合容器化的预期模型。但是有一些很容易想象的情况,您可能希望将网络请求从一个容器内的服务发送到主机上的服务。也许您正在缓慢、有条不紊地从本地运行的单体迁移到在容器中运行的微服务。这是我目前面临的挑战,谷歌搜索将我带到了这里。
  • 确认。感谢您的建设性批评。
  • 我的用例是写入日志机器,当我在多个物理主机上的容器中运行相同的应用程序时,想知道它来自哪个物理主机
  • 在运行 docker 时,不必添加额外的参数比必须添加额外的参数要好。这是我的用例。
  • 就我而言,我想自动创建 AWS 警报,并且我需要主机的主机名,否则 AWS 将不知道我在说什么。
【解决方案4】:

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

通过添加:

docker run --net host

【讨论】:

  • 你能澄清你的答案吗?关于发帖人原来的问题,你是不是建议他跑docker run --net host bar
  • 该命令实际上是docker run --net=host。注意= 符号。
  • 请注意注意事项。运行--network=host 有很多其他含义。它可能适用于特定系统,也可能不适用于特定系统。 (出于完全不同的原因,我实际上将它用于一个系统)。此外,它是特定于 Linux 的,无法在 Mac 或 Windows 上运行。
【解决方案5】:

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

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

然后你可以通过docker ps获取进程ID并查看环境

$ 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

【讨论】:

【解决方案6】:

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

在主机上,将已知的可用 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

【讨论】:

  • 感谢您,我通读了 docker 问题,这是我对 docker-compose 项目的首选解决方案
【解决方案7】:
 HOSTIP=`ip -4 addr show scope global dev eth0 | grep inet | awk '{print $2}' | cut -d / -f 1 | sed -n 1p`
 docker run  --add-host=myhost:${HOSTIP} --rm -it debian

现在您可以访问别名“myhost”下的主机

第一行不会在cygwin上运行,但你可以想办法用ipconfig获取本地IP地址。

【讨论】:

    【解决方案8】:

    我跑了

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

    在我的容器内。

    【讨论】:

    • 您是否正在运行 Docker-in-Docker 容器?大多数容器中不会安装 docker。
    • 我做的
    • 更简单,你可以使用 docker info --format '{{ .Name }}'
    【解决方案9】:

    我知道这是一个老问题,但我也需要这个解决方案,我很喜欢另一个解决方案。

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

    HOST=`hostname --fqdn`
    

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

    echo "Value: $HOST"
    

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 2015-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-15
      相关资源
      最近更新 更多