Noureddine RAMDI / Alpine Android Docker images: a lightweight matrix for reproducible Android CI builds

Created Sat, 23 May 2026 20:41:14 +0000 Modified Sat, 23 May 2026 20:41:27 +0000

alvr/alpine-android

Alpine Android tackles a common pain point in Android development pipelines: providing a lightweight, reproducible build environment for CI/CD. Instead of a monolithic image, it uses a clever single Dockerfile with build arguments to generate a matrix of images that cover multiple Android API levels and Java Development Kit versions. This approach addresses the usual tradeoff between image size, completeness, and build determinism.

What alpine android docker images provide and how they are built

Alpine Android is a collection of small Docker images designed specifically for building and testing Android applications in continuous integration and deployment pipelines. The images are based on Alpine Linux, a minimal Linux distribution known for a tiny footprint, and BellSoft Liberica OpenJDK, a fully open-source Java implementation.

The key architectural choice is to support four JDK variants — versions 8, 11, 17, and 21 — combined with Android API levels ranging from 28 to 37. This results in a matrix of over 40 Docker image tags, each targeting a specific combination of the Android SDK platform and JDK version.

Under the hood, a single Dockerfile uses build arguments to customize the installed components, including platform-tools, build-tools, and platform SDKs tailored per API level. The images are versioned by date to ensure reproducibility, which is crucial for CI environments where deterministic builds are needed.

The base images are all derived from bellsoft/liberica-openjdk-alpine, which provides a robust JDK environment on top of Alpine Linux. On top of this, the Android SDK components are installed selectively to minimize the image size while still providing all necessary tools for building Android apps.

The project also supports extending these images further by adding components via the Android SDK’s sdkmanager or Alpine’s package manager apk add, allowing teams to customize their build environments as needed.

Technical strengths and design tradeoffs

What sets Alpine Android apart is the disciplined approach to managing a large matrix of images through a single Dockerfile and build system. This reduces duplication and maintenance overhead while enabling precise control over the environment.

The use of Alpine Linux as the base ensures the images have a minimal footprint, avoiding the bloat typically associated with full Debian or Ubuntu-based Android SDK images. This is a critical advantage in CI/CD scenarios where image size impacts build speed and resource usage.

Using BellSoft Liberica OpenJDK aligns well with the open-source ethos and ensures compatibility with various JDK versions that Android developers might require. Supporting JDK 8 through 21 covers a broad range of Android Gradle Plugin and build tool versions.

The matrix tagging strategy is well thought out, using clear suffixes to indicate the JDK version and Android API level, making it easy to pull exactly the image needed. The date-based versioning adds a layer of reproducibility, addressing the common CI challenge of floating tags leading to non-deterministic builds.

However, this approach introduces complexity in managing and building many images. Teams consuming these images must be aware of the specific tag corresponding to their build requirements, which can increase cognitive load. Also, Alpine’s musl libc base may occasionally cause compatibility issues with some native Android tooling, although the project mitigates this by careful selection of components.

Overall, the code and build setup prioritize reproducibility, minimalism, and flexibility, all key for production CI environments.

Quick start with alpine android docker images

The project README provides clear guidance on the image variants and tagging scheme. There are four main variants based on the JDK version:

  • JDK8 images are based on Liberica JDK 8u462 and use the tag suffix -jdk8.
  • JDK11 images are based on Liberica JDK 11.0.28 and use the tag suffix -jdk11.
  • JDK17 images are based on Liberica JDK 17.0.16 and use the tag suffix -jdk17.
  • JDK21 images are based on Liberica JDK 21.0.8 and use the tag suffix -jdk21.

Which JDK to use depends on your Android Gradle Plugin version compatibility:

JDK versionAGP version
8= 7.0.0 && = 8.0.0
21>= 8.2.1

The tagging scheme for API levels and JDK variants is as follows:

| API level         | JDK8              | JDK11                     | JDK17                     | JDK21              |
|-------------------|-------------------|---------------------------|---------------------------|--------------------|
| Base Image        | `jdk8` `latest-jdk8` | `jdk11`, `latest-jdk11`  | `jdk17`, `latest`, `latest-jdk17` | `jdk21`, `latest-jdk21` |
| Android 9.0 (28)  | `android-28-jdk8` | `android-28`, `android-28-jdk11` | `android-28-jdk17`        | `android-28-jdk21` |
| Android 10 (29)   | `android-29-jdk8` | `android-29`, `android-29-jdk11` | `android-29-jdk17`        | `android-29-jdk21` |
| Android 11 (30)   | `android-30-jdk8` | `android-30`, `android-30-jdk11` | `android-30-jdk17`        | `android-30-jdk21` |
| Android 12 (31)   | `android-31-jdk8` | `android-31`, `android-31-jdk11` | `android-31-jdk17`        | `android-31-jdk21` |

Pulling the image matching your target Android API level and JDK version allows you to have a consistent build environment. From there, you can extend or customize with your own Dockerfile or use the sdkmanager tool inside.

verdict

Alpine Android fills a very specific but important niche: providing deterministic, lightweight Docker images for Android builds in CI/CD. Its design cleverly balances minimal image sizes with broad coverage of Android API levels and JDK versions.

If you maintain Android projects with complex build requirements or need to ensure reproducibility in your CI pipeline, this repo offers a practical foundation. The use of Alpine Linux and BellSoft Liberica OpenJDK keeps the images slim and open.

The tradeoff is the complexity of managing multiple image tags and ensuring your CI scripts target the correct variant. Also, Alpine’s musl libc base may not be a perfect fit for every native dependency, so teams should test accordingly.

For teams looking for an out-of-the-box, full Android SDK image without concern for size or version granularity, larger Debian-based images might be simpler. But for those who optimize for CI speed, reproducibility, and flexibility, Alpine Android is worth understanding and trying.


→ GitHub Repo: alvr/alpine-android ⭐ 447 · Dockerfile