容器中使用 hostname 访问外部服务, 不需要配置 /etc/hosts
AWS 上有一个集群服务, VPS 之间使用 ip-xx-xx-xx-xx 是可以直接访问的.
现在有个需求, 要在某几台机器部署 docker, 在容器内访问集群内的服务. 并且使用 hostname 实现.
# 创建 Dockerfile
cat > Dockerfile << EOF
FROM alpine
EOF
# 创建 docker-compose.yml
cat > docker-compose.yml << EOF
version: '3'
services:
api:
build: .
container_name: "api"
working_dir: /root
command: tail -f /dev/null
EOF
# 启动容器
docker-compose up -d
# 在容器内尝试连接宿主机, 提示解析不到主机
docker-compose exec api nslookup `hostname`
# nslookup: can't resolve '(null)': Name does not resolve
# nslookup: can't resolve 'ip-172-31-42-98': Name does not resolve
# 在宿主机内解析自己
nslookup ip-172-31-42-98
#Server: 172.31.0.2
#Address: 172.31.0.2#53
#Non-authoritative answer:
#Name: ip-172-31-42-98.us-west-2.compute.internal
#Address: 172.31.42.98
# 查看宿主机 DNS 设置
cat /etc/resolv.conf
# nameserver 172.31.0.2
# search us-west-2.compute.internal
# nameserver 8.8.8.8
# nameserver 8.8.8.8
# 查看容器内 DNS 设置
docker-compose exec api cat /etc/resolv.conf
# search us-west-2.compute.internal
# nameserver 127.0.0.11
# options ndots:0
# 尝试将 `nameserver 172.31.0.2` 加入容器内 DNS 设置后再尝试, 依旧解析失败.
# 直接解析完整路径, 是可以解析到内容的
docker-compose exec mmm nslookup ip-172-31-42-98.us-west-2.compute.internal
#nslookup: can't resolve '(null)': Name does not resolve
#Name: ip-172-31-42-98.us-west-2.compute.internal
#Address 1: 172.31.42.98 ip-172-31-42-98.us-west-2.compute.internal
容器内 DNS 有一行设置是 options ndots:0
, 只需要将 ndots 改成 1 就可以解决这个问题.
ndots:n.
sets a threshold for the number of dots which must appear in a name given to res_query(3) (see resolver(3)) before an initial absolute query will be made. The default for n is 1, meaning that if there are any dots in a name, the name will be tried first as an absolute name before any search list elements are appended to it. The value for this option is silently capped to 15.
以解析的域名ip-172-31-42-98
为例, 里面最少需要有1个 .
, 依次和search
配置的列表拼接解析, 直到解析成功. linux 默认是 1. docker 容器默认是 1, 应该是为了安全考虑.
所以只需要修改 DNS ndots:1
即可.
如何让容器启动后默认就是 ndots:1? 只需要配置 /etc/docker/daemon.json
即可.
{
"dns-opts": ["ndots:1"]
}
# 修改 daemon 后重启 docker
service docker restart
# 重新创建容器
docker-compose down
docker-compose up -d
# 查看配置 ndots 是否有变化
docker-compose exec api cat /etc/resolv.conf
# search us-west-2.compute.internal
# nameserver 127.0.0.11
# options ndots:1
# 解析成功了
docker-compose exec api nslookup ip-172-31-42-98
# Name: ip-172-31-42-98
# Address 1: 172.31.42.98 ip-172-31-42-98.us-west-2.compute.internal
# 访问其他主机的服务
docker-compose exec mmm curl ip-172-31-41-9:31267/echo/
# OK
参考
man/5/resolv.conf - https://linux.die.net/man/5/resolv.conf
moby/moby - ndots:0 #32093 - https://github.com/moby/moby/issues/32093#issuecomment-313887120