jdk-fips

A base image bundling OpenJDK with the Bouncy Castle FIPS crypto libraries, for building Java applications that must comply with FIPS 140-3.

jre-fips, openjdk, adoptium-jdk-fips, openjdk-fips

What is jdk-fips?

The jdk-fips image bundles OpenJDK with the Bouncy Castle FIPS-validated cryptographic libraries (BCFIPS and BCJSSE), pre-configured to replace the default JCA/JCE providers. This makes it a ready-to-use base image for building and compiling Java applications in environments that require FIPS 140-3 compliance — such as FedRAMP-authorized systems, U.S. federal workloads, and regulated industries like finance and healthcare.

Unlike a standard OpenJDK image, jdk-fips routes all cryptographic operations through Bouncy Castle's validated modules, enforcing approved algorithms and blocking disallowed ones at the JVM level. The image ships with a set of validation tests in /usr/lib/bcfips-policy-140-3 that confirm the correct providers are active and that algorithm restrictions are in effect.

It is used as a build-stage base image — the full JDK is needed for compiling and packaging Java applications, while the paired jre-fips image is the intended runtime target.

How to use this image

The jdk-fips image is designed to be used as a build stage in multi-stage Dockerfiles, with jre-fips as the runtime target. Because BCFIPS is loaded via the module path, java -jar cannot be used directly — instead, the module path or classpath must be set explicitly.

Build and package a Java application with jdk-fips, then run it on jre-fips:

FROM registry.echo.ai/jdk-fips:openjdk-21 AS builder
WORKDIR /src
COPY MyApp.java .
RUN javac --class-path "${JAVA_FIPS_CLASSPATH}:." ${JDK_JAVAC_FIPS_OPTIONS} MyApp.java && \
    jar cvf my-app.jar *.class
FROM registry.echo.ai/jre-fips:openjdk-21
WORKDIR /jars
COPY --from=builder /src/my-app.jar .
ENV CLASSPATH="${JAVA_FIPS_CLASSPATH}:/jars/*"
CMD ["MyApp"]
The environment variables JAVA_FIPS_CLASSPATH and JDK_JAVA_FIPS_OPTIONS are pre-set in the image and wire in the Bouncy Castle providers automatically. To run a standalone jar that can't use CLASSPATH, use --module-path instead:
java --module-path /usr/share/java/bouncycastle-fips -jar my-app.jar

After the container starts, all JCA/JCE cryptographic operations are handled by the BCFIPS and BCJSSE providers. Algorithms not permitted under FIPS 140-3 are blocked at runtime rather than silently falling back to non-compliant implementations.

Image variants

Published under registry.echo.ai/jdk-fips, the image is versioned by OpenJDK release:

  • jdk-fips:openjdk-21 — Based on OpenJDK 21 (LTS). The recommended tag for new projects requiring long-term support and FIPS compliance.
  • jdk-fips:openjdk-17 — Based on OpenJDK 17 (LTS). For teams on the previous LTS release that are not yet ready to move to 21.
  • jdk-fips:latest — Tracks the most recent supported OpenJDK version. Useful for evaluation but not recommended for production builds where reproducibility matters.

The jdk-fips image is strictly a build-time image. For production container images, pair it with the matching jre-fips variant to keep the runtime footprint minimal and avoid shipping compiler tooling into production.

Interested in base images that start and stay clean?