OpenJDK 8环境下nonProxyHosts配置不生效问题求助
http.nonProxyHosts配置失效的问题 我之前在维护依赖JDK 8的服务时,也碰到过完全一样的问题——-Dhttp.nonProxyHosts的配置在Docker里被彻底忽略,切换到OpenJDK 9就正常,但又没法升级JDK版本。试过取消引号、转义竖线都没用,最后摸索出几个可行的解决方案,分享给你:
方案1:修正Docker CMD的shell转义方式
问题的核心在于,Docker默认的CMD用shell模式执行时,竖线|会被bash当作管道符解析,而不是完整传递给Java虚拟机。你可以改用exec形式的CMD,或者调整引号的使用方式,确保参数完整传递:
方式A:使用exec形式的CMD(推荐)
FROM openjdk:8 ADD *.jar /service.jar VOLUME /tmp EXPOSE 8080 ENV TZ=CET RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone CMD ["sh", "-c", "echo 'The Service will start...' && java -DsocksProxyHost=192.168.1.250 -Dhttp.nonProxyHosts=\"192.168.1.5|192.168.1.36\" -jar /service.jar"]
这里用["sh", "-c", "..."]的exec格式,同时对双引号进行转义,确保http.nonProxyHosts的完整值被Java接收。
方式B:用单引号包裹参数值
也可以直接用单引号把http.nonProxyHosts的值包起来,单引号在shell中不会解析特殊字符:
CMD echo "The Service will start..." && \ java -DsocksProxyHost=192.168.1.250 -Dhttp.nonProxyHosts='192.168.1.5|192.168.1.36' -jar /service.jar
方案2:使用Java系统属性文件配置
如果不想在命令行里纠结转义问题,可以直接修改Java的net.properties配置文件,把代理参数写进去:
- 在项目中创建一个
net.properties文件,内容如下:
socksProxyHost=192.168.1.250 http.nonProxyHosts=192.168.1.5|192.168.1.36
- 在Dockerfile中添加复制命令,把这个文件覆盖到JRE的配置目录:
FROM openjdk:8 ADD *.jar /service.jar COPY net.properties $JAVA_HOME/jre/lib/net.properties # 添加这行 VOLUME /tmp EXPOSE 8080 ENV TZ=CET RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone CMD echo "The Service will start..." && java -jar /service.jar
这样启动Java时会自动读取这个配置文件,不需要再传-D参数,彻底避开shell转义的坑。
方案3:通过环境变量传递参数
把代理配置放到环境变量中,再在CMD里引用,也能避免shell解析的问题:
FROM openjdk:8 ADD *.jar /service.jar VOLUME /tmp EXPOSE 8080 ENV TZ=CET ENV SOCKS_PROXY_HOST=192.168.1.250 ENV NON_PROXY_HOSTS="192.168.1.5|192.168.1.36" RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone CMD echo "The Service will start..." && \ java -DsocksProxyHost=$SOCKS_PROXY_HOST -Dhttp.nonProxyHosts="$NON_PROXY_HOSTS" -jar /service.jar
这里用双引号包裹$NON_PROXY_HOSTS,确保变量展开时竖线不会被shell解析。
为什么Java 8会有这个问题?
Java 8对http.nonProxyHosts的参数格式校验和解析逻辑比Java 9更严格,而且在Docker的shell执行环境下,特殊字符(比如竖线)会被提前处理,导致Java实际收到的参数并不是你预期的完整列表。Java 9在参数处理上做了优化,能更好地兼容shell环境下的参数传递,所以不会出现这个问题。
内容的提问来源于stack exchange,提问作者Antal Attila

