你如何使Docker容器使用主机的'/etc/hosts'文件?

93

我希望能够使我的Docker容器使用与运行主机相同的 /etc/hosts 设置。有没有方法可以做到这一点?

我知道有一个 --add-host 选项可用于 docker run,但这并不是我想要的,因为不同的主机可能有不同的 /etc/hosts 文件,所以使用 --add-host 硬编码精确的IP地址/主机名称并不理想。


2
我敢建议,也许你更想将容器的DNS设置为考虑主机的/etc/hosts(间接地)。我曾经遇到过同样的情况,我的解决方案是编辑/etc/docker/daemon.json以指向一个简单的DNS代理,该代理读取/etc/hosts - Ondra Žižka
有点晚了,但是...这里说守护进程的/etc/hosts将被使用:https://docs.docker.com/config/containers/container-networking/#dns-services不幸的是,在我的情况下这并没有起作用... - Clerenz
12个回答

88

docker run命令中使用--network=host。这会告诉Docker让容器使用主机的网络堆栈。您可以在这里了解更多。


7
在Mac或Windows上,如何处理没有“host”网络的情况? - Ondra Žižka
12
在许多情况下(例如堆栈、Swarm等),主机网络根本不是一个选择。 - Clerenz
10
使用--network=host显然有助于解决这个问题,但所有使用此选项的人都应该注意其他后果,例如一个简单的例子,它会将Dockerfile中提到的所有端口映射并开放到互联网上 - JOduMonT
4
强调@OndraŽižka的评论:“主机网络驱动程序仅适用于Linux主机,并不支持Docker Desktop for Mac,Docker Desktop for Windows或Docker EE for Windows Server。” - Micah Smith

31

添加一个标准的hosts文件 -

docker run -it ubuntu cat /etc/hosts
添加一个服务器“foo”的映射 -
docker run -it --add-host foo:10.0.0.3 ubuntu cat /etc/hosts
在多个服务器上添加映射。
docker run -it --add-host foo:10.0.0.3 --add-host bar:10.7.3.21 ubuntu cat /etc/hosts

参考资料 - Docker现在支持添加主机映射


参考:使用 --add-host 选项与 docker run 命令 https://docs.docker.com/engine/reference/commandline/run/#add-entries-to-container-hosts-file---add-host - nakamume
2
参考:在docker-compose文件中使用extra_hosts https://docs.docker.com/compose/compose-file/#extra_hosts - nakamume
1
@nakamume 现在链接为 https://docs.docker.com/compose/compose-file/compose-file-v3/#extra_hosts 和 https://docs.docker.com/compose/compose-file/compose-file-v2/#extra_hosts-1 - scipilot

28

14

你也可以通过以下命令在主机上安装dnsmasq:

sudo apt-get install dnsmasq

然后你需要添加文件/etc/docker/daemon.json,并将以下内容添加到其中:

{
    "dns": ["host_ip_address", "8.8.8.8"],
}

接下来,您需要使用命令sudo service docker restart重新启动Docker服务。

此选项强制每个Docker容器都使用主机DNS选项。或者您可以将其用于单个容器,命令行选项由此链接解释。还支持docker-compose选项(您可以通过此链接了解更多信息)。


低估的评论。这是一个更好的解决方案。 - wes
不错。但是Docker部分在Rancher和Kubernetes上不起作用。 - qräbnö
很好的答案。只需记得将“host_ip_address”替换为您主机的实际IP地址。 - rtribaldos
在Ubuntu上,如果端口53已经被占用,请参考https://askubuntu.com/a/1170073/710474 - Arigion
这是一个正确的解决方案。使用 network-mode:hosts 不是。 - janithcooray

9
如果您正在使用docker-compose.yml文件,则相应的属性为:
services:
  xxx:
    network_mode: "host"

Source


7

将以下内容添加到您的运行命令中:

-v /etc/hosts:/etc/hosts

16
一开始看起来这应该能够奏效,但是Docker容器的/etc/hosts文件是为容器量身定制的,因此替换该文件会产生影响。 - StampyCode
2
它对我有效。但是当外部的/etc/hosts被更改时,容器内部不会自动更新。需要重新启动才能更新。 - dashohoxha
1
是的,它可以工作,但这不是一个好主意...真的很冒险。 - Hantlowt

5
如果信任的用户启动您的容器,您可以使用一个shell函数来轻松地“复制”您需要的/etc/hosts条目:
add_host_opt() { awk "/\\<${1}\\>/ {print \"--add-host $1:\" \$1}" /etc/hosts; }

接下来可以这样做:

docker run $(add_host_opt host.name) ubuntu cat /etc/hosts

这样你就不必硬编码IP地址了。


2
主机的/etc/hosts文件无法挂载到容器中。但是您可以将一个文件夹挂载到容器中。并且您需要一个dnsmasq容器。"最初的回答"
  1. A new folder on host machine

     mkdir -p ~/new_hosts/
    
     ln  /etc/hosts ~/new_hosts/hosts
    
  2. mount the ~/new_hosts/ into container

     docker run -it -v ~/new_hosts/:/new_hosts centos /bin/bash
    
  3. Config dnsmasq use /new_hosts/hosts to resolve name.

  4. Change your container's DNS server. Use the dnsmasq container's IP address.

如果您更改主机上的/etc/hosts文件,则dnsmasq容器的/new_hosts/hosts将随之更改。
我发现了一个问题:

dnsmasq容器中的文件/new_hosts/hosts可能会更改。但是新的主机无法解析。因为dnsmasq使用inotify监听更改事件。当您在主机上修改文件时,dnsmasq无法接收到信号,因此不会更新配置。因此,您需要编写守护进程来读取/new_hosts/hosts文件内容并将其每次写入另一个文件。并更改dnsmasq配置以使用新文件。

"最初的回答"

1
实际上,您可以从主机挂载/etc/hosts,而且您可以将其以只读方式挂载:-v /etc/hosts:/etc/hosts:ro - Akom

1
我遇到了同样的问题,并发现这可能与容器化概念相矛盾! 然而,我通过以下方式将/etc/hosts中的每个(ip host)对添加到正在运行的现有容器中来解决我的问题:
1. docker stop your-container-name 2. systemctl stop docker 3. vi /var/lib/docker/containers/*your-container-ID*/hostconfig.json
在文本中找到ExtraHosts并将null替换为"ExtraHosts":["your.domain-name.com":"it.s.ip.addr"]
4. systemctl start docker 5. docker start your-container-name 如果您可以停止并重新运行容器,则情况会更好,只需这样做即可。但是,如果您不想像我一样销毁您的容器,那么这将是一个好的解决方案。

0
如果您正在运行虚拟机以运行Docker容器,如果有主机(虚拟机等)您希望您的容器知道,根据您使用的VM软件,您将必须确保主机机器(托管VM的主机)上有条目,以便您希望容器能够解析的任何机器。
这是因为VM及其容器将在其resolv.conf文件中具有主机机器(VM的主机)的IP地址。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接