Java 服务无法识别将自签名证书导入 Docker 的 JRE cacert

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41497871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:25:32  来源:igfitidea点击:

Importing self-signed cert into Docker's JRE cacert is not recognized by the service

javadockerhttpsdocker-composedocker-machine

提问by Zeigeist

  • A Java Service is running inside the Docker container, which access the external HTTPS url and its self-sign certificate is unavailable to the service/ JRE cacert keystore and therefore connection fails.
  • Hence imported the self-signed certificate of HTTPS external URL into Docker container's JRE cacert keystore. (after checking the $JAVA_HOMEenv. variable)
  • Restarted the Docker container (using docker restartcommand), hoping that the service is also get restarted and pick the changes from JRE cacert. But this didn't happen, the Java service still fails to access external HTTPS URL.
  • Java 服务在 Docker 容器内运行,它访问外部 HTTPS url,其自签名证书对服务/JRE cacert 密钥库不可用,因此连接失败。
  • 因此将 HTTPS 外部 URL 的自签名证书导入到 Docker 容器的 JRE cacert 密钥库中。(检查$JAVA_HOMEenv. 变量后)
  • 重新启动 Docker 容器(使用docker restart命令),希望服务也重新启动并从 JRE cacert 中选择更改。但这并没有发生,Java 服务仍然无法访问外部 HTTPS URL。

Any idea how a Java service running inside the Docker container pick the JRE cacert changes with new certificate import?

知道在 Docker 容器内运行的 Java 服务如何通过新证书导入来选择 JRE cacert 更改吗?

采纳答案by VonC

Hence imported the self-signed certificate of HTTPS external URL into Docker container's JRE cacert keystore.

因此将 HTTPS 外部 URL 的自签名证书导入到 Docker 容器的 JRE cacert 密钥库中。

No: you need to import it into the Docker imagefrom which you run your container.

否:您需要将其导入到运行容器的 Docker映像中。

Importing it into the container would only create a temporary writable data layer, which will be discarded when you restart your container.

将其导入容器只会创建一个临时的可写数据层,当您重新启动容器时,它将被丢弃。

Something like this answer:

这样的答案

USER root
COPY ldap.cer $JAVA_HOME/jre/lib/security
RUN \
    cd $JAVA_HOME/jre/lib/security \
    && keytool -keystore cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias ldapcert -file ldap.cer

回答by Volker Seibt

For using already configured java based containers like jenkins, sonarqubeor nexus(e. g. if you run your own build server) I find it more convenient to mount a suitable cacerts-file into these containers with a parameter for docker run .

对于使用已经配置的基于 Java 的容器,如jenkinssonarqubenexus(例如,如果您运行自己的构建服务器),我发现将合适的cacerts文件挂载到这些容器中并带有 docker run 参数更方便。

I use the cacertsfile from openjdkas base:

我使用cacerts来自openjdk的文件作为基础:

  1. extracting cacertsfrom openjdkimage using a temporary container:
  1. 使用临时容器cacertsopenjdk图像中提取:
docker pull openjdk:latest
docker run --rm --entrypoint cat openjdk:latest /etc/ssl/certs/java/cacerts > cacerts
  1. adding certificate to the extracted cacertsusing a temporary container started from the same folder which also contains ldap.cer:
  1. cacerts使用从同一文件夹启动的临时容器向提取的证书添加证书,该文件夹还包含ldap.cer
docker run --rm -v `pwd`:/tmp/certs openjdk:latest bash -c 'cd /tmp/certs && keytool -keystore cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias buenting-root -file ldap.cer'
  1. run your target docker container(s) mounting the extracted cacertswith a run-parameter, e. g. for sonarqube:
  1. 运行您的目标 docker 容器cacerts,使用运行参数安装提取的内容,例如sonarqube
docker run ... -v /path/to/your/prepared/cacerts:/etc/ssl/certs/java/cacerts:ro ... sonarqube:lts

If there is a new version of openjdkyou can update the cacerts-file on the host with commands from 1. and 2.

如果有新版本的openjdk,您可以cacerts使用 1. 和 2 中的命令更新主机上的 -file。

For updating the target image (e. g. sonarqube) you do not need to create your own image using Dockerfileand docker build.

要更新目标图像(例如sonarqube),您不需要使用Dockerfile和创建自己的图像docker build

回答by povisenko

Here is my solution that worked for me within an image based on OpenJDK Java 11.

这是我在基于OpenJDK Java 11的图像中对我有用的解决方案。

The very first thing to mention that use can use either JDK image or JRE with required ca-certificates-javainstalled for the second choice

首先要提到的是,使用可以使用 JDK 映像或 JRE 并ca-certificates-java为第二选择安装所需

Here is the solution for JDK based image:

以下是基于 JDK 的映像的解决方案:

FROM openjdk:11-jdk-slim
WORKDIR /opt/workdir/

#.crt file in the same folder as your Dockerfile
ARG CERT="certificate.crt"

#import cert into java
COPY $CERT /opt/workdir/
RUN keytool -importcert -file $CERT -alias $CERT -cacerts -storepass changeit -noprompt

...

And here is JREbased image:

这是基于JRE的图像:

FROM openjdk:11-jre-slim
WORKDIR /opt/workdir/

#installing ca-certificates-java to import the certificate
RUN mkdir -p /usr/share/man/man1 \
    && apt-get update \
    && apt-get install -y ca-certificates-java

#.crt file in the same folder as your Dockerfile
ARG CERT="certificate.crt"

#import cert into java
COPY $CERT /opt/workdir/
RUN keytool -importcert -file $CERT -alias $CERT -cacerts -storepass changeit -noprompt

...