容器在运行时默认使用独立网络命名空间,容器内的 /etc/hosts 文件由 Docker 在启动时自动生成。如果想让容器通过一个自定义域名访问宿主机或内网中的某台机器,直接编辑容器里的 /etc/hosts 并不推荐,因为容器重建后修改会丢失。Docker 提供了 --add-host 参数,可以在启动阶段把自定义主机映射写入容器的 /etc/hosts,无需改镜像,也不依赖外部 DNS。本文会从参数原理、docker run 和 docker compose 两种用法以及常见验证与排错几个角度展开。

--add-host 参数的工作原理
每个 Linux 容器启动后都会有一个 /etc/hosts 文件。这个文件里至少包含容器自己的主机名与 IP 地址,以及网关、其他已连接网络中的容器条目。操作系统在进行域名解析时,会先查询 /etc/hosts,再根据 /etc/nsswitch.conf 的配置决定是否继续走 DNS。因此,往 /etc/hosts 里追加一条域名到 IP 的映射,就能让容器内的进程直接访问该域名。
--add-host 的语法是 --add-host=主机名:IP地址,也可以写作 --add-host 主机名:IP地址。Docker 会把这条记录追加到容器 /etc/hosts 文件的末尾。如果要一次加入多条映射,可以重复使用这个参数,每条对应一个主机名。和已经废弃的 --link 相比,--add-host 不要求目标容器存在,也不依赖 Docker 网络内的服务发现,只要目标 IP 可达即可,因此更适合对接宿主机上的固定端口或外部测试环境。
需要明确的是,这种映射只存在于当前容器的文件系统层。容器删除后配置不会保留,重新创建时必须再次指定参数。对于 docker compose 管理的服务,可以把配置写入 YAML 文件,从而保证每次重建服务都带上相同的主机映射。
在 docker run 和 docker compose 中配置主机映射
最直接的用法是在 docker run 命令中追加 --add-host。下面这条命令启动一个 Nginx 容器,并让容器内的 api.internal 指向 192.168.1.50。
docker run -d \ --name web \ --add-host api.internal:192.168.1.50 \ nginx:latest
这里使用反斜杠只是为了在 shell 中换行,执行时实际仍是一条完整命令。如果想要一条命令加入多个主机映射,只需要写多个 --add-host 参数即可,Docker 会全部追加到 /etc/hosts。
docker run -d \ --name web \ --add-host db.internal:192.168.1.51 \ --add-host cache.internal:192.168.1.52 \ --add-host api.internal:192.168.1.50 \ nginx:latest
从 Docker 20.10 开始,可以使用 host-gateway 这个特殊值,让容器通过网关访问宿主机。很多开发场景需要容器访问宿主机上的数据库或调试端口,过去要用 --network host 或手工拼宿主机的内网 IP,现在可以直接写 --add-host host.docker.internal:host-gateway。这是在 Linux 上访问宿主机最省事的方式之一。
docker run -d \ --name web \ --add-host host.docker.internal:host-gateway \ nginx:latest
如果服务由 docker compose 管理,可以在服务定义里使用 extra_hosts 字段。它和 docker run 的 --add-host 效果相同,但写在 YAML 中更便于团队共享和版本管理。下面是一个示例:
services:
web:
image: nginx:latest
extra_hosts:
- "api.internal:192.168.1.50"
- "db.internal:192.168.1.51"
- "host.docker.internal:host-gateway"
YAML 中每个条目需要用字符串形式书写,并注意冒号后的 IP 不要加空格,否则可能被解析为键值对。执行 docker compose up -d 后,进入容器查看 /etc/hosts 就能看到这些追加的记录。
如何验证映射是否生效及常见问题
配置完成后,建议先查看容器内 /etc/hosts 文件的实际内容,确认 Docker 是否正确写入了映射。执行 docker exec web cat /etc/hosts,输出中应该包含我们自己添加的域名和 IP。如果容器里没有 cat,也可以使用 docker exec web getent hosts api.internal 直接查询解析结果。
docker exec web cat /etc/hosts docker exec web getent hosts api.internal docker exec web ping api.internal
getent hosts 比 ping 更轻量,而且某些精简镜像可能没有安装 ping 命令。只要返回了 IP 地址,就说明 /etc/hosts 中的映射已经生效。对于 HTTP 服务,还可以进一步用 curl 发起请求验证端口连通性。
使用过程中最常见的误区是以为 --add-host 支持通配符域名,例如想把所有 *.internal 都指向某个 IP。实际上它只支持精确主机名,不支持 *.ipipp.com 这种写法。如果需要泛域名解析,应该考虑在容器内配置 dnsmasq 或使用自定义 DNS 服务器。
另一个容易忽略的问题是容器重建后的配置丢失。手动执行 docker exec 修改运行中容器的 /etc/hosts 虽然能临时生效,但容器一旦被删除并重新创建,这些手动修改就会消失。正确的做法是把主机映射放在 docker run 参数或 compose 文件中,而不是在运行后临时编辑文件。同时要注意,/etc/hosts 的优先级通常高于 DNS,因此可以用它临时覆盖公网域名的解析结果,适合做灰度测试或故障模拟,但并不适合作为生产环境中的服务发现方案。
Docker--add-host主机映射修改时间:2026-10-02 12:53:53