在Docker Alpine Linux容器上运行Scala SBT时的证书exception

我有一个Dockerfile与下面的基本映像:

FROM frolvlad/alpine-oraclejdk8:slim

在同一个Dockerfile中,我也运行: activator compile

当我运行$ docker build -t some_name . 在我的MacBook上,SBT步骤按预期工作。

当我在远程Ubuntu主机(AWS上的EC2实例)上运行相同的命令时,通过相同的Dockerfile,我得到了许多证书错误,如下所示:

 [info] Resolving org.webjars#strip-json-comments;1.0.2-1 ... [error] Server access Error: java.security.cert.CertificateException: No name matching repo.typesafe.com found url=https://repo.typesafe.com/typesafe/ivy-releases/org.webjars/strip-json-comments/1.0.2-1/ivys/ivy.xml [error] Server access Error: java.security.cert.CertificateException: No name matching repo.scala-sbt.org found url=https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/org.webjars/strip-json-comments/1.0.2-1/ivys/ivy.xml [error] Server access Error: java.security.cert.CertificateException: No name matching repo1.maven.org found url=https://repo1.maven.org/maven2/org/webjars/strip-json-comments/1.0.2-1/strip-json-comments-1.0.2-1.pom [info] Resolving com.typesafe.sbt#sbt-rjs;1.0.7 ... [error] Server access Error: java.security.cert.CertificateException: No name matching repo.typesafe.com found url=https://repo.typesafe.com/typesafe/ivy-releases/com.typesafe.sbt/sbt-rjs/scala_2.10/sbt_0.13/1.0.7/ivys/ivy.xml [error] Server access Error: java.security.cert.CertificateException: No name matching repo.scala-sbt.org found url=https://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/com.typesafe.sbt/sbt-rjs/scala_2.10/sbt_0.13/1.0.7/ivys/ivy.xml [error] Server access Error: java.security.cert.CertificateException: No name matching repo1.maven.org found url=https://repo1.maven.org/maven2/com/typesafe/sbt/sbt-rjs_2.10_0.13/1.0.7/sbt-rjs-1.0.7.pom 

看来SBT正在联系存储库来下载依赖关系,并且无法validation他们的SSL证书。 然而,当docker build在我的MacBook上运行时,相同的过程可以正常工作,并且可以下载相关的堆,而不会有任何问题。 因此,看起来我的MacBook和Ubuntu主机之间的环境存在一些差异。 但是,无论Docker在哪里运行,Docker都将提供完全的隔离和一致的行为。

有没有人有关于可能发生的事情的线索?

我相信我发现了这个问题,虽然我无法解释为什么会发生。

显示与Docker行为不一致的EC2 Ubuntu主机有一个像这样的iptables规则:

 $ sudo iptables -L -t nat [...] Chain xyz (1 references) target prot opt source destination REDIRECT tcp -- anywhere anywhere tcp dpt:https /* xyz */ redir ports 8443 

该规则适用于将所有入站stream量从端口443redirect到8443.这意味着将stream量redirect到在同一台计算机上运行且具有自签名SSL证书的基于Java的应用程序。

当我使用Docker的默认networking设置在同一台机器上运行Docker容器时,我从容器,Docker或OS中发出HTTPS wget似乎将outbout连接redirect到Ubuntu主机上的端口8443,因此到本地的基于Java的应用程序,而这些应用程序又接受连接(大部分时间),并返回导致之前观察到的java.security.cert.CertificateException的无效(自签名)证书详细信息。

但是, iptables规则应该只影响到主机的入站连接。 任何人都可以解释为什么来自Docker容器内的出站连接被redirect到本地端口?

这些iptables设置如何影响Docker?

Image frolvlad/alpine-oraclejdk8:slim不使用Alpine的官方Java包,而是使用glibc hack使Oracle JDK(仅作为针对glibc编译的二进制文件分发)以基于musl的系统运行。 这不是 Alpine支持的,我强烈build议你不要使用它。

你应该使用openjdk:8-alpine图像,或者只是简单的Alpine图像,只需安装openjdk8包。 SBT在这里工作正常。


如果你想尝试最新的版本,现在还包括IcedTea的补丁,那么使用普通的Alpine图像,并从边缘分支安装openjdk8:

 echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories apk update apk add openjdk8 

混合来自稳定和边缘的软件包通常不是一个好主意,可能存在ABI不兼容问题。 因此,将系统升级到edge会更好:在/etc/apk/repositories v3.X/mainreplace为edge/main并运行apk update && apk upgrade


Oracle JDK只是OpenJDK(即开源)的品牌(专有)分发版,代码库几乎完全相同。 这意味着几乎所有在Oracle JDK 8上运行的Java应用程序也都在OpenJDK 8上运行。

您可以在gliderlabs / docker-alpine的评论中find更多信息。