Container images for the Microsoft Build of OpenJDK

This article provides information on the available container images for the Microsoft Build of OpenJDK.

Linux-based images

We currently supply Linux-based container images for Ubuntu and Microsoft CBL-Mariner, now known as Azure Linux. The images are published in the Microsoft Artifact Registry located at mcr.microsoft.com/openjdk/jdk.

To pull the latest image for a specific tag, use the following command:

docker pull mcr.microsoft.com/openjdk/jdk:<tag>

The following table shows the tag to use for your Linux distribution and JDK version.

Base OS OpenJDK 21 OpenJDK 17 OpenJDK 11 OpenJDK 8
Ubuntu 22.04 21-ubuntu 17-ubuntu 11-ubuntu N/A
CBL Mariner 2.0 21-mariner 17-mariner 11-mariner 8-mariner
CBL-Mariner 2.0 Distroless 21-distroless 17-distroless 11-distroless 8-distroless

Note: Images for OpenJDK 8 ship with binaries of Eclipse Temurin, from the Eclipse Adoptium project.

Architectures

The images above are offered for both amd64 and arm64 architectures. Your container runtime shall pull the right image based on your environment. To force a pull of an image for a specific architecture, use the following:

$ docker pull --platform=linux/arm64 mcr.microsoft.com/openjdk/jdk:21-mariner

To force an architecture inside a Dockerfile, you may use the following:

FROM --platform=linux/arm64 mcr.microsoft.com/openjdk/jdk:21-mariner AS build
# ...

For more information on building multi-platform container images, check the documentation of your container runtime. For example, Docker and Podman.

How to use these images

Create a Dockerfile with the following contents:

# Example using MS Build of OpenJDK image directly
FROM mcr.microsoft.com/openjdk/jdk:21-ubuntu

# Continue with your application deployment
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

Distroless

The distroless images are based on the CBL-Mariner 2.0 distribution by Microsoft. They require a different approach to deploying an application. Because the distroless images do not contain a complete Linux distribution, there is no shell, for example.

The ENTRYPOINT of these images is already configured pointing to the java command. Consuming Dockerfiles must use the CMD instruction to complete the command-line arguments of the JVM launcher process.

Create a Dockerfile with the following contents:

FROM mcr.microsoft.com/openjdk/jdk:21-distroless

COPY app.jar /app.jar

CMD ["-Xmx256m", "-jar", "/app.jar"]

Use a different Base OS image or version

If you prefer to use a different OS base image distribution, you can copy the JDK from an existing pre-built image using the COPY --from instruction in a Dockerfile, similar to the following example:

# Example using MS Build of OpenJDK image with a different base image
FROM debian:buster-slim
ENV LANG en_US.UTF-8
ENV JAVA_HOME /usr/lib/jvm/msopenjdk-21-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=mcr.microsoft.com/openjdk/jdk:21-ubuntu $JAVA_HOME $JAVA_HOME

# Continue with your application deployment
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

You can also install the JDK using either yum or apt-get, or simply extracting a tar.gz file and configuring JAVA_HOME accordingly. Read more.

Use a different version of Ubuntu

To deploy Microsoft Build of OpenJDK on different versions of Ubuntu base images, Microsoft recommends that users author their own Dockerfiles. For reference, the below Dockerfile builds an image with Ubuntu 24.04.

# Example using MS Build of OpenJDK image with a different version of Ubuntu
FROM ubuntu:24.04
ENV LANG en_US.UTF-8
ENV JAVA_HOME /usr/lib/jvm/msopenjdk-21-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=mcr.microsoft.com/openjdk/jdk:21-ubuntu $JAVA_HOME $JAVA_HOME

# Continue with your application deployment
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

Alpine images

While Microsoft does not supply Alpine-based images, we do supply a limited set of musl-compiled JDK binaries for Alpine Linux.

Users are welcome to create container images for Alpine Linux using the available binaries.

Create a Dockerfile with the following contents:

FROM alpine:latest

ENV JAVA_HOME=/usr/lib/jdk
ENV PATH=${PATH}:${JAVA_HOME}/bin

# Default to UTF-8 file.encoding
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'

# (Optional) Add extra packages for fontconfig and ttf-dejavu to support server-side image generation
RUN apk add --no-cache fontconfig libretls musl-locales musl-locales-lang ttf-dejavu tzdata zlib \
    && rm -rf /var/cache/apk/*

# Download and extract JDK 17
RUN wget -nv -O jdk.tar.gz https://aka.ms/download-jdk/microsoft-jdk-17-alpine-x64.tar.gz && \
    mkdir $JAVA_HOME && \
    tar xf jdk.tar.gz -C $JAVA_HOME --strip-components 1 --no-same-owner

# Copy the application
COPY app.jar /app.jar

CMD [ "java", "-jar", "/app.jar" ]

Create a custom Java runtime

To create a custom Java runtime image, use a multi-stage Dockerfile similar to the following example:

# Example of custom Java runtime using jlink in a multi-stage container build
FROM mcr.microsoft.com/openjdk/jdk:21-ubuntu as runtime-build

# Create a custom Java runtime
RUN $JAVA_HOME/bin/jlink \
         --add-modules java.base \
         --strip-debug \
         --no-man-pages \
         --no-header-files \
         --compress=2 \
         --output /javaruntime

# Define your base image. You may use any base OS and version of your choice.
FROM debian:buster-slim
ENV LANG en_US.UTF-8
ENV JAVA_HOME /usr/lib/jvm/msopenjdk-21-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=runtime-build /javaruntime $JAVA_HOME

# Continue with your application deployment
RUN mkdir /opt/app
COPY japp.jar /opt/app
CMD ["java", "-jar", "/opt/app/japp.jar"]

For more information on creating custom Java runtimes, see Java Runtimes with jlink

Non-root user

The images come with an app user that can be optionally enabled and used by consuming layers:

FROM mcr.microsoft.com/openjdk/jdk:21-mariner

WORKDIR /home/app
COPY japp.jar japp.jar
USER app

CMD ["java", "-jar", "/opt/app/japp.jar"]

In the above example, the application binary is copied as root, since the images remain with root by default. The application then is executed as app. The folder /home/app is also owned by user app, giving the application a writeable filesystem.

Default locale

The images for Microsoft Build of OpenJDK are configured by default with the en_US.UTF-8 locale. If you want to use a different locale, or a different base image as described previously, you'll need to manually configure environment variables in your own Dockerfile, and make sure the locale you want is installed.

For example, to use the pt_BR.UTF-8 locale on an Ubuntu-based image, you can add the following lines to your Dockerfile:

...
USER root
RUN apt-get update
RUN apt-get install -y locales

RUN sed -i '/pt_BR.UTF-8/s/^# //g' /etc/locale.gen
RUN locale-gen

ENV LANG pt_BR.UTF-8
ENV LANGUAGE pt_BR:pt
ENV LC_ALL pt_BR.UTF-8
...

This Dockerfile is provided as an example. It is not meant to suggest the most optimal configurations.

Stay on older minor versions

Microsoft Build of OpenJDK container images are only available under the tags listed previously. We don't supply tags for minor versions, and the major version tags always have the latest minor version to ensure that developers will have the latest update for any given major version.

These base images use the underlying package manager mechanism of the Linux distributions to install the JDK package. Therefore, to stay on a particular older version, you will need to use tools such as apt-get or yum to install the specific minor version of the JDK.

To rollback to specific versions on different base OS images outside the list of supplied images, for example debian:buster-slim, you can use the same approach below either in the first stage of a muli-stage container image build, or as part of a traditional Linux package installation flow. For more information, see the Install on Ubuntu 18.04+ section of Install the Microsoft Build of OpenJDK.

For CBL-Mariner and other OS images based on RPM/yum, see the details provided later in this article.

For Ubuntu, and other Debian-based images, you can display all available minor versions published in the Microsoft Linux repositories, as shown in the following Bash example showing commands and output. The commands shown here assume the Microsoft Linux repository is configured, as described at Install on Ubuntu 18.04+.

$ docker run --pull=always -ti --rm mcr.microsoft.com/openjdk/jdk:11-ubuntu
root@c60eacd7dd7d:/# apt-get update
...

root@c60eacd7dd7d:/# apt-cache madison msopenjdk-11
msopenjdk-11 |  11.0.23-1 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 |  11.0.22-1 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 |  11.0.21-1 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 | 11.0.20.1-1 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 |  11.0.20-3 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 |  11.0.20-2 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 |  11.0.20-1 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 |  11.0.19-1 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
msopenjdk-11 |  11.0.18-1 | https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 Packages
...

This Bash example shows how to have your image revert msopenjdk-11 to an older version, say 11.0.16-1:

root@dd24eca5bdb3:/# java -version
openjdk version "11.0.23" 2024-04-16 LTS
OpenJDK Runtime Environment Microsoft-9394293 (build 11.0.23+9-LTS)
OpenJDK 64-Bit Server VM Microsoft-9394293 (build 11.0.23+9-LTS, mixed mode, sharing)

root@a93cd1ed8783:/# apt-get -y install -y --allow-downgrades msopenjdk-11=11.0.16-1
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  fonts-dejavu
The following NEW packages will be installed:
  fonts-dejavu
The following packages will be DOWNGRADED:
  msopenjdk-11
0 upgraded, 1 newly installed, 1 downgraded, 0 to remove and 0 not upgraded.
Need to get 194 MB of archives.
After this operation, 13.0 MB disk space will be freed.
Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-dejavu all 2.37-2build1 [3,192 B]
Get:2 https://packages.microsoft.com/ubuntu/22.04/prod jammy/main amd64 msopenjdk-11 amd64 11.0.16-1 [194 MB]
Fetched 194 MB in 18s (10.7 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package fonts-dejavu.
(Reading database ... 9151 files and directories currently installed.)
Preparing to unpack .../fonts-dejavu_2.37-2build1_all.deb ...
Unpacking fonts-dejavu (2.37-2build1) ...
dpkg: warning: downgrading msopenjdk-11 from 11.0.23-1 to 11.0.16-1
Preparing to unpack .../msopenjdk-11_11.0.16-1_amd64.deb ...
update-alternatives: using /usr/lib/jvm/msopenjdk-11-amd64/lib/jfr to provide /usr/bin/jfr (jfr) in auto mode
Unpacking msopenjdk-11 (11.0.16-1) over (11.0.23-1) ...
Setting up fonts-dejavu (2.37-2build1) ...
Setting up msopenjdk-11 (11.0.16-1) ...

To do the same thing in your Dockerfile, use the following commands:

FROM mcr.microsoft.com/openjdk/jdk:11-ubuntu
...
RUN apt-get update && \
    apt-get install -y --allow-downgrades msopenjdk-11=11.0.16-1
...

This Bash example uses CBL-Mariner based images:

root [ / ]# java -version
openjdk version "11.0.15" 2022-04-19 LTS
OpenJDK Runtime Environment Microsoft-32930 (build 11.0.15+10-LTS)
OpenJDK 64-Bit Server VM Microsoft-32930 (build 11.0.15+10-LTS, mixed mode)

root [ / ]# yum update
...

root [ / ]# yum list msopenjdk-11
Loaded plugin: tdnfrepogpgcheck
msopenjdk-11.x86_64   11.0.14+9_LTS-1    @System
msopenjdk-11.x86_64   11.0.10+9-1        packages-microsoft-com-prod
msopenjdk-11.x86_64   11.0.11+9-1        packages-microsoft-com-prod
msopenjdk-11.x86_64   11.0.12+7-1        packages-microsoft-com-prod
msopenjdk-11.x86_64   11.0.13+8_LTS-1    packages-microsoft-com-prod
msopenjdk-11.x86_64   11.0.14+9_LTS-1    packages-microsoft-com-prod

root [ / ]# yum install -y --nogpgcheck msopenjdk-11-11.0.15-1
Loaded plugin: tdnfrepogpgcheck

Downgrading:
msopenjdk-11  x86_64  11.0.15-1  mariner-official-microsoft  308.10M  183.75M

Total installed size: 308.10M
Total download size: 183.75M
msopenjdk-11                         192678446 100%
Testing transaction
Running transaction
Installing/Updating: msopenjdk-11-11.0.15-1.x86_64
Removing: msopenjdk-11-11.0.23-1.x86_64

To do the same thing in your Dockerfile, use the following commands:

FROM mcr.microsoft.com/openjdk/jdk:11-mariner
...
RUN yum update && \
    yum install -y --nogpgcheck msopenjdk-11-11.0.15-1
...

Container image rebuild schedule

To ensure the highest level of security and stability, our container images are rebuilt every Monday, Wednesday, and Friday. This regular rebuild schedule enables us to promptly incorporate the latest security patches and updates.

You can expect the following benefits from this rebuild schedule:

  • Timely security updates: By rebuilding the images three times a week, we ensure that any new security vulnerabilities are addressed quickly.
  • Improved stability: Regular updates help maintain the stability and performance of your applications by including the latest bug fixes and improvements.

If you have any questions or encounter issues related to these updates, refer to this schedule before you open a support ticket.

For more information on our support policies, see Support roadmap for the Microsoft Build of OpenJDK.

Windows-based images

We currently do not supply Windows-based container images.

Provide feedback on the Microsoft Build of OpenJDK

Send us your comments, thoughts, and ideas to help us improve the Microsoft Build of OpenJDK. Visit our OpenJDK discussions page on GitHub to send us your feedback.

Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.