如何从没有env vars的主机上的docker容器内获取docker主机的主机名

Dav*_*Xia 47 docker

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

foo.example.com (docker host)
  bar (docker container)
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

其中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.
Run Code Online (Sandbox Code Playgroud)

运行状况检查将循环查找上面第一个SRV记录,因此需要知道其主机名.

在旁边

我正在使用Helios并且发现它为我添加了一个env var,我可以从中获取主机名.但我只是好奇,以防我使用没有Helios的码头工具.

Moh*_*ady 22

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

docker run .. -e HOST_HOSTNAME=`hostname` ..
Run Code Online (Sandbox Code Playgroud)

运用

-e HOST_HOSTNAME=`hostname`
Run Code Online (Sandbox Code Playgroud)

将调用主机名并将其作为环境变量返回HOST_HOSTNAME,当然您可以根据需要自定义键.

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

docker run .. -e HOST_HOSTNAME=(hostname) ..
Run Code Online (Sandbox Code Playgroud)

  • 我想知道是否有办法在不使用env vars的情况下做到这一点. (5认同)
  • 不幸的是,当将“.env”文件与“docker-compose”一起使用时,环境变量方法不起作用,但您可以在“environment:”部分中使用“$HOSTNAME”。 (3认同)

Phi*_*hil 16

好的,这不是主机名(正如OP所要求的那样),但这将从容器内部解析为您的docker主机以用于连接目的。

host.docker.internal
Run Code Online (Sandbox Code Playgroud)

当我搜索此内容时,我被重定向到这里。


sea*_*mcl 14

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

  • 像"很难想象你为什么要这样"这样的评论是无益和粗鲁的.当然,从绿色字段开始,此请求不符合预期的容器化模型.但是有一些容易想象的情况,您可能希望将网络请求从一个容器内的服务发送到主机上的服务.也许你正在慢慢地,有条不紊地从一个本地运行的monolith迁移到运行在容器中的微服务.这是我目前的挑战和谷歌搜索解决方案带我到这里. (94认同)
  • 确认.感谢建设性的批评. (11认同)
  • 我的用例是写入日志机器,并希望知道当我在多个物理主机上的容器中运行相同的应用程序时它来自哪个物理主机 (9认同)
  • 就我而言,我想自动创建 AWS 警报,并且需要主机的主机名,否则 AWS 不会知道我在说什么。 (3认同)
  • 在运行 docker 时,不必添加额外的参数比不必添加额外的参数要好。那是我的用例。 (2认同)
  • 我想用构建它们的主机名来标记随机分配到集群中一个节点的构建。帮助调试各种问题。 (2认同)

Gor*_*onM 12

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

docker run -h=my.docker.container.example.com ubuntu:latest
Run Code Online (Sandbox Code Playgroud)

您可以使用反引号(或shell使用的任何等效项)将hosthame的输出转换为-h参数.

docker run -h=`hostname` ubuntu:latest
Run Code Online (Sandbox Code Playgroud)

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

  • 这是最好的答案,因为它将修改 `uname` 系统调用的输出。这样,它将与“hostname”程序或其他 C 编写的程序(例如 Python 的“socket.gethostname()”)一起使用。更改“HOSTNAME”环境变量或将“/etc/hostname”安装到容器不会执行此操作。 (2认同)

azD*_*Dev 6

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

通过添加:

docker run --net host
Run Code Online (Sandbox Code Playgroud)

  • 你能澄清你的答案吗?关于发布者的原始问题,您是否建议他运行docker run --net host bar? (2认同)
  • 该命令实际上是`docker run --net=host`。注意 `=` 符号。 (2认同)

Arc*_*ano 6

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

docker service create -e 'FOO={{.Node.Hostname}}' nginx  
Run Code Online (Sandbox Code Playgroud)

然后您可以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
Run Code Online (Sandbox Code Playgroud)

使用 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
Run Code Online (Sandbox Code Playgroud)

  • 像“.Node.Hostname”这样的占位符记录在 https://docs.docker.com/engine/reference/commandline/service_create/#create-services-using-templates (4认同)

Ada*_*tle 5

我认为我遇到同样问题的原因是最新的Docker for Mac beta中的一个错误,但是在那里的评论中,我能够找到适合我和我的团队的解决方案.我们正在将其用于本地开发,我们需要我们的集装箱化服务,以便在我们努力取代它时与单块进行通信.这可能不是一种生产可行的解决方案.

在主机上,将已知的可用IP地址别名为loopback接口:

$ sudo ifconfig lo0 alias 10.200.10.1/24
Run Code Online (Sandbox Code Playgroud)

然后将具有主机名的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"
Run Code Online (Sandbox Code Playgroud)

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

$ docker exec -it container_name /bin/bash
$ wget relevant_hostname/index.html
$ cat index.html
Run Code Online (Sandbox Code Playgroud)