dhi.io/azul
Azul Platform Prime delivers optimizes Java application performance and drives cloud cost efficiency.
All examples in this guide use the public image. If you’ve mirrored the repository for your own use (for example, to your Docker Hub namespace), update your commands to reference the mirrored image instead of the public one.
For example:
dhi.io/azul:<tag><your-namespace>/dhi-azul:<tag>For the examples, you must first use docker login dhi.io to authenticate to the registry to pull the images.
This Docker Hardened Azul Platform Prime image includes a complete, high-performance Java development and runtime environment powered by Azul Zing JVM in a single, security-hardened package:
java for running applicationsjavac for compiling Java source codejar for creating JAR filesjps, jstat, and other diagnostic toolsUnlike standard JDKs, Azul Zing delivers:
Note: While this image includes full JDK capabilities, it maintains security hardening by excluding shell access and system utilities.
Run the following command to display the Java help information. Replace <tag> with the image variant you want to run.
docker run --rm dhi.io/azul:<tag>
To check the Java version:
docker run --rm dhi.io/azul:<tag> java -version
Run your compiled Java application directly from the container. Mount your local JAR file and run it:
docker run -v $(pwd):/app dhi.io/azul:<tag> java -jar /app/myapp.jar
Since the image includes javac, you can compile and run Java applications directly:
Create a Java file:
echo 'public class Hello { public static void main(String[] args) { System.out.println("Hello from Azul Zing!"); } }' > Hello.java
Compile and run:
# Compile the Java file
docker run -v $(pwd):/app -w /app dhi.io/azul:<tag> javac Hello.java
# Run the compiled class
docker run -v $(pwd):/app -w /app dhi.io/azul:<tag> java Hello
Build a JAR file using the included jar tool:
# Create a manifest file
echo "Main-Class: Hello" > Manifest.txt
# Create the JAR
docker run -v $(pwd):/app -w /app dhi.io/azul:<tag> jar cvfm hello.jar Manifest.txt Hello.class
# Run the JAR
docker run -v $(pwd):/app -w /app dhi.io/azul:<tag> java -jar hello.jar
Note: Since the image has no shell, RUN commands won't work. Compile your code outside the container or use a different build image:
# Option 1: Use a different image for building
FROM openjdk:21 AS builder
WORKDIR /app
COPY *.java .
RUN javac *.java
RUN jar cvf app.jar *.class
# Runtime stage with DHI
FROM dhi.io/azul:21-jdk-prime
WORKDIR /app
COPY --from=builder /app/app.jar .
CMD ["java", "-cp", "app.jar", "Main"]
Alternatively, compile locally and copy only the JAR:
FROM dhi.io/azul:21-jdk-prime
WORKDIR /app
COPY app.jar .
CMD ["java", "-jar", "app.jar"]
Azul Zing comes with the C4 garbage collector enabled by default for pauseless operation. You can tune memory settings:
# Run with specific heap size
docker run -v $(pwd):/app dhi.io/azul:<tag> \
java -Xmx512m -Xms512m \
-jar /app/myapp.jar
Use built-in monitoring tools to track application performance:
# Start your application
docker run -d --name my-app -v $(pwd):/app dhi.io/azul:<tag> java -jar /app/myapp.jar
# List Java processes (note: limited without shell, but jps works)
docker exec my-app jps
# Clean up
docker stop my-app && docker rm my-app
| Feature | Docker Official Azul/OpenJDK | Docker Hardened Azul Platform Prime |
|---|---|---|
| Security | Standard base with common utilities | Minimal, hardened base with security patches |
| Shell access | Full shell (bash/sh) available | No shell |
| Package manager | apt/apk available | No package manager |
| User | Runs as root by default | Runs as nonroot user |
| Attack surface | Larger due to additional utilities | Minimal, only Java tools |
| Debugging | Traditional shell debugging | Use Docker Debug for troubleshooting |
| Base OS | Various Alpine/Debian versions | Hardened Debian 13 base |
| JVM | Standard OpenJDK or Azul Zulu | Azul Zing with C4 GC |
| JDK Tools | Varies by image | Full JDK included (javac, jar, etc.) |
Docker Hardened Images prioritize security through minimalism:
While the image includes full JDK capabilities for Java development and runtime needs, it intentionally excludes system utilities and shell access to maintain security hardening.
The hardened images don't contain a shell nor system tools for debugging. Common debugging methods for applications built with Docker Hardened Images include:
Docker Debug provides a shell, common debugging tools, and lets you install other tools in an ephemeral, writable layer that only exists during the debugging session.
For example, you can use Docker Debug:
docker debug <container-name>
The Azul Docker Hardened Images are available as runtime images that include full JDK capabilities in two flavors:
Azul Platform Prime (Zing): High-performance JVM optimized for low-latency, pauseless operation using the C4 GC and Falcon JIT.
<major>-jdk-prime (example: 21-jdk-prime)Azul Zulu (OpenJDK builds): Production-ready, certified OpenJDK builds from Azul suitable for general-purpose Java workloads.
<major>-jdk-zulu (examples: 17-jdk-zulu, 21-jdk-zulu)Common characteristics for both variants:
These images are designed to run your application in production while still providing the ability to compile and package
Java code when needed. They are intended to be used either directly or as the FROM image in a Dockerfile.
Note: No separate dev variants are available as the runtime images include the full JDK toolchain.
To migrate your application to a Docker Hardened Image, you must update your Dockerfile. At minimum, you must update the base image in your existing Dockerfile to a Docker Hardened Image. This and a few other common changes are listed in the following table of migration notes:
| Item | Migration note |
|---|---|
| Base image | Replace your base images in your Dockerfile with a Docker Hardened Image. |
| Package management | Images don't contain package managers. Install dependencies using multi-stage builds with other images if needed. |
| Non-root user | Images run as the nonroot user. Ensure that necessary files and directories are accessible to the nonroot user. |
| Multi-stage build | Can use the same image for both build and runtime stages since full JDK is included, or optimize with multi-stage builds. |
| TLS certificates | Docker Hardened Images contain standard TLS certificates by default. There is no need to install TLS certificates. |
| Ports | Images run as a nonroot user by default. Applications can't bind to privileged ports (below 1024) when running in Kubernetes or in Docker Engine versions older than 20.10. Configure your Java application to use ports above 1024. |
| Entry point | Default command is java --help. Override with your application's entry point. |
| No shell | Images don't contain a shell. Cannot use shell scripts or commands that require shell interpretation. |
| JAVA_HOME | The JAVA_HOME environment variable is set to /opt/zing/zing-jdk${MAJOR_VERSION}. Adjust your scripts if they rely on a different path. |
| JVM Type | These images use Azul Zing JVM, not standard OpenJDK. Review any JVM-specific flags or configurations. |
The following steps outline the general migration process.
Find hardened images for your app.
Azul Platform Prime images are available in versions 11, 17, and 21. Choose the version that matches your application's requirements.
Update the base image in your Dockerfile.
Update the base image in your application's Dockerfile to the hardened image:
FROM dhi.io/azul:21-jdk-prime
Adjust for no shell.
Since there's no shell, you cannot use shell scripts or commands that require shell interpretation. Use Java directly or compile commands into your application.
Handle file permissions.
The image runs as nonroot user. Ensure files are accessible:
COPY --chown=65532:65532 app.jar /app/app.jar
Configure ports.
Use ports above 1024:
EXPOSE 8080
The following are common issues that you may encounter during migration.
The hardened images don't contain a shell nor system tools for debugging. The recommended method for debugging is to use Docker Debug to attach to containers. Docker Debug provides a shell, common debugging tools, and lets you install other tools in an ephemeral, writable layer that only exists during the debugging session.
You can also use the included JVM diagnostic tools:
docker exec <container> jps
docker exec <container> jstat -gc <pid>
Images run as the nonroot user (UID 65532). Ensure that necessary files and directories are accessible to the nonroot user. You may need to copy files to different directories or change permissions so your application can access them.
Non-root users can't bind to privileged ports (below 1024) when running in Kubernetes or in Docker Engine versions older than 20.10. Configure your Java applications to listen on ports 8080, 8443, or other ports above 1024.
Images don't contain a shell. You cannot:
Instead, run Java commands directly or build functionality into your application.
The default command is java --help. Always specify your application's entry point:
CMD ["java", "-jar", "/app/myapp.jar"]
Azul Zulu is now supported as an alternate DHI flavor for users who prefer certified OpenJDK builds from Azul. Zulu images provide a more traditional OpenJDK experience (compatible with HotSpot garbage collectors and JIT) and are suitable for general-purpose Java workloads, while Azul Platform Prime (Zing) focuses on low-latency, pauseless operation.
Key differences between the two DHI flavors:
When to choose Zulu:
How to run Zulu images with DHI tags:
dhi.io/azul:17-jdk-zulu, dhi.io/azul:21-jdk-zulu,
dhi.io/azul:11-jdk-zulu.Examples:
# Run Java help
docker run --rm dhi.io/azul:17-jdk-zulu
# Check Java version
docker run --rm dhi.io/azul:17-jdk-zulu java -version
# Run a JAR
docker run -v $(pwd):/app dhi.io/azul:17-jdk-zulu java -jar /app/myapp.jar
Note: For Zulu variants, JAVA_HOME is set to /opt/zulu/zulu-jdk<MAJOR_VERSION> and PATH is updated accordingly.
Azul Zing comes pre-configured with optimized settings. Key considerations:
-Xmx and -Xms as neededApplications using Java Native Interface (JNI) should be thoroughly tested with the Debian 13 base and Zing JVM. Ensure:
Azul Zing includes enhanced monitoring capabilities:
# Enable detailed GC logging (note: no shell redirection available)
docker run dhi.io/azul:<tag> \
java -Xlog:gc* \
-jar /app/myapp.jar
# Use JVM diagnostic tools
docker exec <container> jps -l
docker exec <container> jstat -gc <pid> 1000