Self-hosted service
mingchen/docker-android-build-box avatar
mingchen/docker-android-build-box

docker-android-build-box: a fat Docker image for Android CI

An optimized docker image includes Android, Kotlin, Flutter sdk.

624 stars241 forksDockerfileMIT

At a glance

What is it?
The mingc/android-build-box image bundles the Android SDK, several JDKs, Flutter, fastlane, Node and the emulator into one container so a CI job does not have to install a toolchain. The tradeoff is disk and a moving latest tag, and the README is unusually explicit about both.
Who is it for?
Adopt this image if your team builds Android, Flutter or React Native artefacts in CI and you would rather maintain one pinned container than a toolchain install script, and if you have the disk to hold a sixteen gigabyte image plus caches. Do not adopt it for local development on a small disk, because the caching guidance in the README says the extra space can double what the image needs, and do not run on latest in a release pipeline, because that tag always moves.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 22 days ago.
What is it written in?
Mainly Dockerfile, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Everything a mobile build needs in one layer

The image is described as an optimized Docker image that includes the Android SDK and the Flutter SDK, and the contents list in the README is the better description of what optimized means here. The tagged release carries Ubuntu 22.04, four OpenJDK versions at 8, 11, 17 and 21, Android SDK platforms 28 through 35 with matching build tools, the NDK at r28b, bundletool, the Android Emulator, cmake, TestNG, Python 3.8.10, Node.js 22 with npm and React Native, Ruby with RubyGems, fastlane, Flutter 3.32.4 and jEnv for switching Java versions. The four JDKs are the interesting part for anyone who has to build older and newer Android targets in the same pipeline, since jEnv handles the global Java selection inside the container. The image is published as mingc/android-build-box on Docker Hub and the repository also carries a Gemfile for the fastlane side and a test_projects/ directory.

latest always moves, tags do not

There are two ways to consume the image and the difference decides whether your build is reproducible. The latest image always has the latest software installed, including the last eight Android SDKs for platforms along with the associated build tools, and the Docker Hub description carries an always up-to-date listing of what is inside it. The tagged releases are fixed, and the README's advice is to use a tag for a specific stable version rather than latest to avoid breaking your build, with 1.25.0 given as an example. The repository supports that with three documents: the tags list on GitHub, a CHANGELOG.md describing the changes between tags, and COMPATIBILITY.md holding the matrices of the software available on each tagged release and on the latest image. The image itself is built publicly by GitHub Actions from the Dockerfile in the repository, and the README is explicit that there is no hidden stuff in it.

Building a project is one docker run

The usage section is short because the point is that no setup is needed. You change into the project directory and run the container with the working directory mounted, letting the Gradle wrapper do the work:

sh
cd <android project directory>  # change working directory to your project root directory.
docker run --rm -v `pwd`:/project mingc/android-build-box bash -c 'cd /project; ./gradlew build'

For an app bundle you swap the task, and the README gives the variant with ./gradlew bundleRelease. For an interactive shell in the container, the mount is the same but the image is started with a login shell instead:

sh
docker run -v `pwd`:/project -it mingc/android-build-box bash -l

That third form is the one that turns the image into a workstation, since you can then use sdkmanager or jEnv interactively. For pipeline use, the first form is enough, and adding a second mount for the Gradle cache is what keeps the build fast across runs.

Caching trades disk for build time

The caching section is where the README is most candid, and it opens with a warning that caching does not reduce the total disk space needed but increases it, because you pay for the image and then for the cache. The example is concrete: for 1.25.0 the image needs 16.2GB of space, and caching the SDK on top of that would need another 6GB. Three caches are documented, each using a named volume, and the named volume is required so the container contents survive between runs. The jEnv cache binds a host directory to /root/.jenv/ so the global Java selection persists, the Gradle cache binds a host directory to /root/.gradle, and the Android SDK cache binds to /opt/android-sdk/ so platforms and build tools can be added or removed inside the image. Turning the Gradle cache on also needs a setting in gradle.properties, either the project's own file or the global one in the cache directory:

sh
org.gradle.caching=true

Once the SDK is cached, you can prune it from inside the container with the sdkmanager, listing what is installed, uninstalling a platform or installing one, and passing several packages to either flag at once.

The Dockerfile is parameterised, not magic

Because the build recipe is public, the image can be rebuilt with different contents rather than only pulled. The Dockerfile exposes the versions as build arguments, each with a tagged flag and a version, so a stage can either take the latest or the pinned value. The arguments cover the Android SDK tools with the version 13114758 as of 2025-04-04, the NDK at 28.1.13356709, Node at 22.x, bundletool at 1.18.1, Flutter at 3.32.8 and jEnv at 0.5.6, and the set of Android platforms is chosen by an argument whose valid values are last8 or tagged, where last8 grabs the last eight SDKs including extensions and any future build tool release candidates. The base stage is ubuntu:22.04, and the environment is set up with ANDROID_HOME, ANDROID_SDK_HOME, ANDROID_NDK, FLUTTER_HOME and JENV_ROOT pointing into /opt. The repository also keeps an sdk/ directory and a tagged_sdk_packages_list.txt, which is how the list of packages per tag is kept.

One release tag in 2025, commits through 2026

The release history is thin in a way that reflects how this project is used. The single recorded release is 1.29.0 on 2025-04-16, and the last push to the repository was on 2026-10-01, so the Dockerfile and the CI workflow keep moving even though tag history in the repository metadata shows one entry. That is consistent with how the image is consumed, since the latest tag is rebuilt continuously and the tagged releases are the stable points that a pipeline should pin. The licence is MIT, and the project description lists the intended toolchain, including Kotlin and Flutter, with the topic tags naming bitbucket, fastlane, dockerize and pipeline, which matches the fastlane and Bitbucket Pipelines workflows this kind of image exists to serve. The image on Docker Hub is the artefact, and the repository is the recipe and the compatibility documentation for it.

Editorial conclusion

Adopt this image if your team builds Android, Flutter or React Native artefacts in CI and you would rather maintain one pinned container than a toolchain install script, and if you have the disk to hold a sixteen gigabyte image plus caches. Do not adopt it for local development on a small disk, because the caching guidance in the README says the extra space can double what the image needs, and do not run on latest in a release pipeline, because that tag always moves. Verify first which tag you want, reading the compatibility matrices for that tag rather than trusting the latest listing, pin it in your pipeline, and confirm the SDK platform and build tools versions your app needs are the ones that tag contains.

Frequently asked questions

What does the docker-android-build-box image contain?

The tagged release carries Ubuntu 22.04, OpenJDK 8, 11, 17 and 21, Android SDK platforms 28 to 35 with build tools, NDK r28b, bundletool, the Android Emulator, cmake, TestNG, Python 3.8.10, Node.js 22 with npm and React Native, Ruby, fastlane, Flutter 3.32.4 and jEnv.

How do I build an Android project with the image?

Change into the project root and run the container with the directory mounted at /project, invoking the Gradle wrapper inside it, for example docker run --rm -v `pwd`:/project mingc/android-build-box bash -c 'cd /project; ./gradlew build'. Use ./gradlew bundleRelease for an app bundle.

Should I use the latest tag in a production build?

The README suggests using a tag for a specific stable version rather than latest to avoid breaking your build, since the latest image always has the newest software including the last eight Android SDKs. The compatibility matrices in COMPATIBILITY.md list the software per tag.

What does caching the Android SDK cost in disk space?

Caching does not reduce disk use, it increases it, because you pay for the image and then for the cache. The README gives the example of the 1.25.0 image needing 16.2GB, plus another 6GB for the SDK cache, and the caches are implemented with named volumes bound to host directories.

Can I rebuild the image with different SDK versions?

Yes. The Dockerfile exposes build arguments for the SDK tools, the NDK, Node, bundletool, Flutter and jEnv, each with a tagged flag and a version, plus an argument choosing either the last eight Android platforms or a tagged set. The image is built publicly by GitHub Actions from that Dockerfile.

Official sources

  1. License: MIT
  2. mingchen/docker-android-build-box on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mingchen-docker-android-build-box.svg)](https://hysenlabs.com/projects/mingchen-docker-android-build-box)

Was this useful?