如何在 docker 映像中添加 CA 根证书?

我在 Ubuntu 14.04的 Docker 1.13.1容器中运行 ASP.NET Core 1.1 Web API。

当代码试图从 HTTPS 服务器检索某些数据时,我会得到这个证书身份验证错误:

 An error occurred while sending the request. ---> System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates
at System.Net.Http.CurlHandler.ThrowIfCURLEError(CURLcode error)
at System.Net.Http.CurlHandler.MultiAgent.FinishRequest(StrongToWeakReference`1 easyWrapper, CURLcode messageResult)

HTTPS 服务器是由我们公司 CA 签署的内部证书,所以我知道我可能需要注册内部 CA。

到目前为止,我发现的所有关于这个错误和 Docker 谈到让 Docker 本身运行,连接到回购等。我的 Docker 工作正常,而且 Web API 在容器外的 Ubuntu 服务器上运行没有问题。

1)我是否需要在 docker 映像内加入 CA 根证书?

2)如果有,我该怎么做?

3)如果没有,我怎么解决这个问题?

204085 次浏览

The task itself is not specific to docker as you would need to add that CA on a normal system too. There is an answer on the askubuntu community on how to do this.

So in a Dockerfile you would do the following (don't forget chmod in case you're running the container with a user other than root):

ADD your_ca_root.crt /usr/local/share/ca-certificates/foo.crt
RUN chmod 644 /usr/local/share/ca-certificates/foo.crt && update-ca-certificates

It's also worth noting that this definitely needs to use the .crt extension. I initially tried this with a .pem cert file (I thought they were interchangeable, so others might also), which is not linked by update-ca-certificates.

Installing ca-certificates locate cert_file_name.crt file in the same directory as Dockerfile.

# Install ca-certificates
# Please locate cert_file_name.crt file in the same directory as Dockerfile.
COPY cert_file_name.crt /usr/share/ca-certificates/
RUN echo cert_file_name.crt >> /etc/ca-certificates.conf
RUN update-ca-certificates

This will update certificates in the Dockerfile.

To simplify/standardise all container builds, we now host our certificates on a central HTTPS server and build them into our containers like this:

# Debian stretch based container
RUN curl -ks 'https://cert.host.server/ssl_certs/EnterpriseRootCA.crt' -o '/usr/local/share/ca-certificates/EnterpriseRootCA.crt'
RUN /usr/sbin/update-ca-certificates

Alpine-based containers don't have the tools immediately available so require a bit more work to achieve the same:

# Alpine based containers
RUN apk update && apk add curl
WORKDIR /usr/local/share/ca-certificates
RUN curl -ks 'https://cert.host.server/ssl_certs/EnterpriseRootCA.crt' -o '/usr/local/share/ca-certificates/EnterpriseRootCA.crt'
RUN /usr/sbin/update-ca-certificates

If you also want to update your Java truststore (same as on any computer):

RUN keytool -keystore /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias EnterpriseRootCA -file EnterpriseRootCA.crt

Another option is to use OpenSSL. Replace domain_name with the URL you can retrieve the CA

RUN openssl s_client -connect <domain_name>:443 -showcerts </dev/null 2>/dev/null | sed -e '/-----BEGIN/,/-----END/!d' | tee "/usr/local/share/ca-certificates/ca.crt" >/dev/null && \
update-ca-certificates