Custom CA Certificates (Java)
Overview
You can configure Java-based container images (openjdk, etc.) to trust custom Certificate Authority (CA) certificates for TLS connections. Java uses its own truststore format (JKS/PKCS12) rather than PEM files.
Java keystores require a password for integrity checking. The system truststore uses the standard password changeit, which is a well-known default used for tamper detection rather than confidentiality.
Volume Mount Approach
Create a custom truststore using the keytool command. You can either trust only your specific CAs (for internal-only applications) or merge with the default public CAs (typical for applications connecting to both internal and external services).
CERTDIR=$(mktemp -d) # or use a persistent directory for repeated runs
# OPTIONAL: Copy the default Java truststore to merge with public CAs
# Skip this step to trust ONLY your custom CAs
podman run --rm -v "${CERTDIR}:/work:Z" \
quay.io/hummingbird/openjdk:latest \
cp /etc/pki/ca-trust/extracted/java/cacerts /work/cacerts
# Import your custom CA
podman run --rm -v "${CERTDIR}:/work:Z" \
quay.io/hummingbird/openjdk:latest \
keytool -import -noprompt -trustcacerts -alias my-custom-ca \
-file /work/my-ca.crt \
-keystore /work/cacerts \
-storepass changeit -storetype JKS
Podman Example
Mount the custom truststore to the system location:
podman run --rm \
-v "${CERTDIR}/cacerts:/etc/pki/ca-trust/extracted/java/cacerts:ro,Z" \
quay.io/hummingbird/openjdk:latest \
java -jar myapp.jar
Kubernetes Example
In Kubernetes, use an init container to create the truststore, then share it via an emptyDir volume:
apiVersion: v1
kind: ConfigMap
metadata:
name: custom-ca
data:
ca.crt: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
apiVersion: v1
kind: Pod
spec:
initContainers:
- name: prepare-truststore
image: quay.io/hummingbird/openjdk:latest
command: ["sh", "-c"]
args:
- |
# OPTIONAL: Copy the default truststore to merge with public CAs
# Skip this line to trust ONLY your custom CAs
cp /etc/pki/ca-trust/extracted/java/cacerts /truststore/cacerts
chmod 666 /truststore/cacerts
keytool -import -noprompt -trustcacerts -alias custom-ca \
-file /ca/ca.crt -keystore /truststore/cacerts \
-storepass changeit -storetype JKS
volumeMounts:
- name: custom-ca
mountPath: /ca
- name: truststore
mountPath: /truststore
containers:
- name: app
image: quay.io/hummingbird/openjdk:latest
volumeMounts:
- name: truststore
mountPath: /etc/pki/ca-trust/extracted/java
readOnly: true
volumes:
- name: custom-ca
configMap:
name: custom-ca
- name: truststore
emptyDir: {}
For the trust-only-specific-CAs approach, omit the cp command and create the keystore directly with keytool -import.
Derived Image Approach
Use this approach when it’s more practical to bake the certificates into the image instead of generating the truststore on each container startup. This creates a new image with a merged trust store with the trust anchor command.
Create a multi-stage Containerfile with your ca.crt in the build context. This example derives from the openjdk image:
FROM quay.io/hummingbird/openjdk:latest-builder AS builder
USER root
COPY ca.crt /tmp/
RUN trust anchor /tmp/ca.crt
FROM quay.io/hummingbird/openjdk:latest
COPY --from=builder /etc/pki /etc/pki
Build and use your custom image:
podman build -t my-openjdk-with-ca .
podman run --rm my-openjdk-with-ca java -jar myapp.jar