java.net.UnknownHostException 在 Docker
java.net.UnknownHostException on Docker
我正在尝试为 ZooKeeper 创建 docker 个容器并在集群模式下配置它们(完整代码是 here and here)。
容器基于 Alpine Linux(Docker Hub 上的 alpine:3.2),但我要描述的问题也发生在官方 Java 容器( java:7).
我使用以下命令启动集群:
docker run -d -h zk1 --name zk1 dockmob/zookeeper -s zk1,zk2,zk3
# wait some time ...
docker run -d -h zk2 --name zk2 dockmob/zookeeper -s zk1,zk2,zk3
docker run -d -h zk3 --name zk3 dockmob/zookeeper -s zk1,zk2,zk3
(docker hub 上有,你可以试试)。
如果我在启动第二个和第三个容器之前等待一段时间,那么主机名 zk2
和 zk3
被放入 /etc/hosts
太晚了(docker ),并且 Java 无法找到它们:我在 zk1
的日志中得到了 zk2
和 zk3
的 java.net.UnknownHostException
。
我在网上发现我需要禁用JVM DNS缓存才能刷新主机名,所以我在Dockerfile
中引入了以下命令以更新java.security
设置:
RUN grep '^networkaddress.cache.ttl=' /usr/lib/jvm/java-1.7-openjdk/jre/lib/security/java.security || echo 'networkaddress.cache.ttl=10' >> /usr/lib/jvm/java-1.7-openjdk/jre/lib/security/java.security
它将 DNS TTL 属性 (networkaddress.cache.ttl
) 设置为 10
秒。
变量 networkaddress.cache.negative.ttl
已设置为其默认值 (10
)。
行为没有改变。我反复收到很多 java.net.UnknownHostException
。
问题的原因是什么?
我通过切换到 Oracle JRE 8 并在 Dockerfile 中使用以下 hack 设法摆脱了 DNS 问题:
RUN echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
我在 Docker Hub (the code is on github 上创建了一个工作 Java 8 docker 容器容器)。
在我的例子中,java 应用程序在 docker 中 运行 时失败并显示 java.net.UnknownHostException
。原因是我使用了 --network=none
docker 标志(通过 dhcp 和管道获取 ip/hostname)。在这种情况下,docker 不会像
一样自动添加到 /etc/hosts
条目
127.0.0.1 15e326aecf84
和getCanonicalHostName()
Java函数抛出了这个异常。
可能的解决方案:
- 通过
docker run
参数 --hostname=your-hostname.com
将主机名条目添加到 /etc/hosts
文件
- 切换到 docker 托管网络配置
我正在尝试为 ZooKeeper 创建 docker 个容器并在集群模式下配置它们(完整代码是 here and here)。
容器基于 Alpine Linux(Docker Hub 上的 alpine:3.2),但我要描述的问题也发生在官方 Java 容器( java:7).
我使用以下命令启动集群:
docker run -d -h zk1 --name zk1 dockmob/zookeeper -s zk1,zk2,zk3
# wait some time ...
docker run -d -h zk2 --name zk2 dockmob/zookeeper -s zk1,zk2,zk3
docker run -d -h zk3 --name zk3 dockmob/zookeeper -s zk1,zk2,zk3
(docker hub 上有,你可以试试)。
如果我在启动第二个和第三个容器之前等待一段时间,那么主机名 zk2
和 zk3
被放入 /etc/hosts
太晚了(docker ),并且 Java 无法找到它们:我在 zk1
的日志中得到了 zk2
和 zk3
的 java.net.UnknownHostException
。
我在网上发现我需要禁用JVM DNS缓存才能刷新主机名,所以我在Dockerfile
中引入了以下命令以更新java.security
设置:
RUN grep '^networkaddress.cache.ttl=' /usr/lib/jvm/java-1.7-openjdk/jre/lib/security/java.security || echo 'networkaddress.cache.ttl=10' >> /usr/lib/jvm/java-1.7-openjdk/jre/lib/security/java.security
它将 DNS TTL 属性 (networkaddress.cache.ttl
) 设置为 10
秒。
变量 networkaddress.cache.negative.ttl
已设置为其默认值 (10
)。
行为没有改变。我反复收到很多 java.net.UnknownHostException
。
问题的原因是什么?
我通过切换到 Oracle JRE 8 并在 Dockerfile 中使用以下 hack 设法摆脱了 DNS 问题:
RUN echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf
我在 Docker Hub (the code is on github 上创建了一个工作 Java 8 docker 容器容器)。
在我的例子中,java 应用程序在 docker 中 运行 时失败并显示 java.net.UnknownHostException
。原因是我使用了 --network=none
docker 标志(通过 dhcp 和管道获取 ip/hostname)。在这种情况下,docker 不会像
/etc/hosts
条目
127.0.0.1 15e326aecf84
和getCanonicalHostName()
Java函数抛出了这个异常。
可能的解决方案:
- 通过
docker run
参数--hostname=your-hostname.com
将主机名条目添加到 - 切换到 docker 托管网络配置
/etc/hosts
文件