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 provide Linux-based container images for Ubuntu and Microsoft CBL-Mariner. The images are published in the Microsoft Container 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:17-mariner

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

FROM --platform=linux/arm64 mcr.microsoft.com/openjdk/jdk:17-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:17-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:17-distroless

COPY app.jar /app.jar

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

Use a different Base OS image

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-17-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=mcr.microsoft.com/openjdk/jdk:17-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.

Alpine images

While Microsoft does not produce Alpine-based images, we do provide musl-compiled JDK binaries for Alpine Linux.

Users are welcome to create container images for Alpine Linux using our 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:17-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-17-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:17-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, and 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 publish tags for minor versions, and the major version tags always have the latest minor version to ensure that developers will always 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 version, you'll need to use tools such as apt-get or yum to install the specific minor version of the JDK.

To install specific versions on different base OS images, for example debian:buster-slim, you can use the same approach 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 repo 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.15+10-LTS-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.14.1+1-LTS-31205 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.14+9-LTS-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.13+8-LTS-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.12+7-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.11+9-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.10+9-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages

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

root@dd24eca5bdb3:/# 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@dd24eca5bdb3:/# apt-cache madison msopenjdk-11
msopenjdk-11 | 11.0.15+10-LTS-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.14.1+1-LTS-31205 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.14+9-LTS-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.13+8-LTS-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.12+7-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.11+9-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages
msopenjdk-11 | 11.0.10+9-1 | https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages

root@dd24eca5bdb3:/# apt-get -y install -y --allow-downgrades msopenjdk-11=11.0.11+9-1
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be DOWNGRADED:
  msopenjdk-11
0 upgraded, 0 newly installed, 1 downgraded, 0 to remove and 17 not upgraded.
Need to get 193 MB of archives.
After this operation, 353 kB disk space will be freed.
Get:1 https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 msopenjdk-11 amd64 11.0.11+9-1 [193 MB]
Fetched 193 MB in 6s (30.9 MB/s)
debconf: delaying package configuration, since apt-utils is not installed
dpkg: warning: downgrading msopenjdk-11 from 11.0.14+9-LTS-1 to 11.0.11+9-1
(Reading database ... 5936 files and directories currently installed.)
Preparing to unpack .../msopenjdk-11_11.0.11+9-1_amd64.deb ...
Unpacking msopenjdk-11 (11.0.11+9-1) over (11.0.14+9-LTS-1) ...
Setting up msopenjdk-11 (11.0.11+9-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.11+9-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.10+9-1
Loaded plugin: tdnfrepogpgcheck

Downgrading:
msopenjdk-11      x86_64      11.0.10+9-1      packages-microsoft-com-prod      308.38M 323358496

Total installed size: 308.38M 323358496

Downloading:
Testing transaction
Running transaction
Installing/Updating: msopenjdk-11-11.0.10+9-1.x86_64
Removing: msopenjdk-11-11.0.12+7-1.x86_64

Complete!

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.10+9-1
...

Windows-based images

We currently do not provide 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.