How to resolve PKIX Path Building Failed in Docker Container

Consider the following scenario in which a docker container was throwing SSLHandshakeException. You are running a service in a docker container. This service calls another service in another docker container and the API calls fails with following error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target

In this post, I will show how to resolve SSLHandshakeException within docker container with a simple fix.

Previously, I showed how to run your services using docker container in this post.

This scenario is very common with microservices running in docker containers. Also there are few ways you can resolve this issue, but I will suggest a standard way to resolve this issue.

Standard solution is to get SSL certificate of target service and import that certificate in keystore of Java runtime that calling service is using.

Docker Container Logo

How do we resolve Docker Container – SSLHandshakeException?

The dilemma exists because every time you stop docker container and restart or kill a docker container and restart it, it will change container id. With that, you can’t be sure where JAVA_HOME of your calling service exists.

So depending on what Java environment are you using for your docker container, the easiest thing you can do is copy a cacerts keystore file from your local host machine to docker container when building the docker image.

Before you copy cacerts, make sure you import the SSL certificate of the target service. You can use keytool command to import this certificate.

Now add a below command in your Dockerfile

COPY ./cacerts /usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64/jre/lib/security/cacerts

This will build your docker image and will resolve the PKIX Path Building Failed error.

Drawback

A drawback of this solution is that you have to make sure that your base docker image has jvm path mentioned in the command. If it is different from above, you will have to first find that. Also if you call multiple services, you will have to get SSL certificates of all those servies.

One important thing to note that this should not happen in your production environment, but mostly development sandbox. Production environment should have CA signed SSL certificates on load balancer and all your services should be behind that load balancer while sharing the same certificate.

References

  1. Docker Containers – docker