# docker-maven: Maven container images across many JDK distributions

> docker-maven is a repository of Dockerfiles that build Maven container images on top of Eclipse Temurin, IBM Semeru, Amazon Corretto, Azul Zulu and SAP Machine JDKs, across Alpine, Debian, Ubuntu and Windows Server Core bases, with separate Maven 4 variants. The same images are published to Docker Hub under csanchez/maven and to the GitHub Container Registry under ghcr.io/carlossg/maven.

**carlossg/docker-maven** — Official Docker image with Maven

- Repository: https://github.com/carlossg/docker-maven
- Stars: 559 · Forks: 417
- Language: Dockerfile
- License: Apache-2.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/carlossg-docker-maven

## One directory per JDK and base combination

docker-maven is the official Docker image with Maven, and the repository is structured as a matrix rather than as a single build.

The top level directory listing makes the shape obvious. There is an eclipse-temurin family, an amazoncorretto family, an azulzulu family, an ibm-semeru family and a sapmachine family, and within each of them a set of variants named by base image and, in some cases, by Maven major version. So amazoncorretto-17-alpine and amazoncorretto-17-debian and amazoncorretto-17-windowsservercore are three directories, and amazoncorretto-17-debian-maven-4 is a fourth that adds Maven 4 to the same stack.

The reason the matrix exists is that a Maven image is really three choices bundled into one tag. The JDK vendor and major version, the base operating system, and the Maven version itself. A team that needs Maven 3 on JDK 8 on Alpine is not served by the same tag as a team that needs Maven 4 on JDK 21 on Debian, and folding them into one image would mean rebuilding it every time any of the three changed.

The README is essentially the index of that matrix, with a link to the Dockerfile for every combination, for example:

```bash
https://github.com/carlossg/docker-maven/blob/main/eclipse-temurin-17-alpine/Dockerfile
``` Each entry is a link to a file in the repository rather than a reference to a registry page, so the build definition for any tag is readable in the same place as the tag list.

The project is Apache-2.0 licensed, the primary language of the repository is reported as Dockerfile, and the default branch is main. The last push to the repository was on 2026-10-05.

## Three registries, and they do not carry the same tags

The images are published under three names, and the differences between them are the first thing to get right.

The list is csanchez/maven on Docker Hub, maven, which is the Docker official image and is described as linux and extending Docker official images only, and ghcr.io/carlossg/maven on the GitHub Container Registry, which is linux only:

```bash
https://hub.docker.com/r/csanchez/maven
https://hub.docker.com/_/maven
https://github.com/carlossg/docker-maven/pkgs/container/maven
```


So the csanchez/maven repository is the broadest one. It is where the Azul Zulu variants live, which the README calls out explicitly with the note that they are only under csanchez/maven and ghcr.io/carlossg/maven, and it is the natural home for the Windows Server Core builds, since the GitHub Container Registry line is described as linux only.

The official maven image is a different animal by design. It is not this project's own image, it is the Docker official image, and the constraint in the README is that it extends Docker official images only. That is a narrower promise: the official line is maintained to a standard and cannot carry every variant the maintainer builds here.

The ghcr.io/carlossg/maven repository sits in the middle. It is the same maintainer's own publishing channel, it is linux only, and it shares the csanchez tags including the Azul Zulu ones.

For a team, the practical consequence is that the tag you can pull depends on the registry you pull from. That is the kind of detail that turns into a CI failure when a pipeline is switched from Docker Hub to the GitHub Container Registry without checking that the tag exists in both, and it is why the README lists all three at the top rather than burying the answer in a registry page.

For the current list of tags, the README points at Docker Hub or the GitHub Container Registry, since those are where the tags actually live and are kept up to date.

## Reading the tag names as a compatibility statement

The tag vocabulary is worth learning, because the tag name is the entire compatibility contract and nothing else is written down.

The first axis is the JDK vendor. eclipse-temurin covers the Eclipse Adoptium builds from 8 through 27. ibm-semeru covers IBM's Semeru builds for 11, 17, 21, 24 and 25 on Ubuntu Noble. amazoncorretto covers Amazon Corretto for 8, 11, 17, 21 and 25. azulzulu covers Azul Zulu for 8 through 25, and only under the two maintainer-controlled registries. sapmachine covers SAP's Machine builds for 17, 21, 24, 25 and 26.

The second axis is the base image. alpine and noble and resolute appear for the Temurin family, debian and windowsservercore for Corretto and Azul Zulu. Alpine is the interesting one for build images because it is small and uses musl rather than glibc, and a dependency that expects glibc will not behave the same there.

The third axis is the Maven version. The maven-4 suffixed directories, such as amazoncorretto-17-debian-maven-4 and azulzulu-25-alpine-maven-4, are the Maven 4 builds, and they exist as separate directories rather than as a build argument because the two Maven majors need different resolution and different plugins in practice.

Read together, a tag tells you the whole stack: which JDK vendor and major version, which base distribution, and which Maven major. Nothing about the Maven version is implied by the JDK version, which is exactly why the maven-4 variants are separate rather than a suffix you might forget.

One gap in the grid is worth noticing. Temurin has alpine, noble and resolute for most versions but only alpine and resolute for 27, and the Corretto and Zulu families have a windowsservercore variant for several versions but not all. The matrix is not perfectly rectangular, and the README is the place to check rather than assuming a variant exists because its siblings do.

## A shared template and a submodule, rather than fifty hand written files

Two entries in the top level listing explain how the matrix is maintained without fifty hand written Dockerfiles drifting apart.

There is a Dockerfile-template entry at the top level, and there is a.gitmodules file.

A template directory means the per-variant Dockerfiles are not written from scratch. The shared parts, the install of Maven itself, the environment variables, the entrypoint and the working directory, live in one place and are instantiated per variant. When Maven changes how it wants to be installed, or when the base image conventions change, the change happens in the template rather than in every combination, and the matrix cannot fall out of sync because nobody updated the eleven Azul Zulu directories.

The.gitmodules file means that at least part of the build content comes from another repository. That is the standard arrangement when a project wants to reuse the official Docker image definitions rather than reimplementing them, and it also means the build depends on a remote reference that can move. When the official images change, this repository picks up the change through the submodule rather than by copying.

The consequence for a user is a two-layered trust model. The layer you pull is what the registry publishes, and the layer you build is the content in this repository, which depends on content elsewhere. Checking that the image you pull matches the tag you expected is therefore a separate step from trusting the repository, and the tag lists on Docker Hub and the GitHub Container Registry are the place to confirm the versions in play.

The repository also carries README-short.txt next to README.md, which is a shorter variant of the same tag information for people who want the list without the links.

## What this project is not, and the alternative ways to get Maven in a container

The scope is narrow, and it is worth being explicit about it, because the name suggests more than it delivers.

This is a set of images. It is not a Maven distribution, not a Maven plugin, and not a wrapper tool. The Maven project itself is a separate thing that these images package. If you are looking for build caching, dependency caching or a reproducible build pipeline, none of that lives here; what lives here is the container that Maven runs inside.

There are three ways to get a Maven container, and the difference in approach is worth naming.

The first is the official maven image. It is the conservative choice: fewer variants, maintained to a standard, and the one most people end up with. The cost is that you take the JDK distribution and the base image it was built with, rather than choosing them.

The second is this repository's own images. You get a large matrix of vendor and base combinations, Windows Server Core builds for pipelines on Windows, and Maven 4 variants. The cost is that you are choosing from a matrix maintained by one person rather than a standard, so you carry that dependency yourself.

The third is writing your own Dockerfile on top of an existing base. A single FROM line with a JDK base and a Maven install gives you exactly the stack you want and nothing else, and it is a file you own. The cost is that you now maintain it, including the security updates of the base image.

Which one is right depends on how much the JDK vendor matters to your build. If it does not, the official image is the shortest path. If your organisation standardises on a particular JDK distribution, or you need a Windows agent, or you need Maven 4 specifically, then the variants in this repository exist because that combination is not otherwise available.

## Conclusion

docker-maven suits a build pipeline that needs a Maven image on a specific JDK vendor and version, and a team that wants to pick the base image deliberately instead of inheriting whatever the official image ships, including a Windows Server Core variant and Maven 4 builds. It does not suit a project that needs a plugin or a wrapper, because this project is only the images, and it does not suit you if you want release notes per image, since the repository publishes no GitHub releases and the tag list on Docker Hub and the GitHub Container Registry is where the versions are recorded. Check three things before you adopt a tag: which JDK distribution and major version it carries, whether the base is Alpine or a glibc distribution, since that decides whether your native dependencies work, and whether the image you pull is the one you expect, since csanchez/maven, the official maven image and ghcr.io/carlossg/maven do not carry an identical set of tags. The last push to the repository was on 2026-10-05.

## FAQ

### What is docker-maven?

It is the official Docker image with Maven, published as a repository of Dockerfiles that build Maven images on Eclipse Temurin, IBM Semeru, Amazon Corretto, Azul Zulu and SAP Machine JDKs, across Alpine, Debian, Ubuntu Noble and Ubuntu Resolute bases, plus Windows Server Core and Maven 4 variants.

### Where are the docker-maven images published?

Under three names: csanchez/maven on Docker Hub, the official maven image on Docker Hub which extends Docker official images and is linux only, and ghcr.io/carlossg/maven on the GitHub Container Registry, which is linux only. The Azul Zulu variants exist only under the two maintainer-controlled registries.

### What does the maven-4 suffix in a tag mean?

Those directories, such as amazoncorretto-17-debian-maven-4, are the Maven 4 builds for that JDK vendor and base. They exist as separate images rather than as a build option because the two Maven major versions resolve and run plugins differently.

### Does docker-maven publish releases?

No. The repository publishes no GitHub releases, and the current list of tags is kept on Docker Hub and the GitHub Container Registry, with the README linking to those pages and to the Dockerfile for each combination.

### Why is there a Dockerfile-template directory?

The template holds the parts of the image that every variant shares, and the per-variant Dockerfiles are instantiated from it, so a change to how Maven is installed or how the base image is configured does not have to be repeated across every JDK and base combination. The .gitmodules file shows that part of the build content comes from another repository.

## Sources

- [carlossg/docker-maven on GitHub](https://github.com/carlossg/docker-maven)
- [Issues](https://github.com/carlossg/docker-maven/issues)
- [License: Apache-2.0](https://github.com/carlossg/docker-maven/blob/main/LICENSE)
- [README](https://github.com/carlossg/docker-maven/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/carlossg-docker-maven
