Building Android apps in Docker is a powerful way to create a clean, portable, and reproducible environment, especially useful for developers and CI/CD systems. In this guide, I’ll walk you through creating a custom Docker image to build Android apps with:
- Ubuntu 24.04 as the base image
- Android command-line tools and SDK
- SDKMAN for managing multiple Java versions
- A script that automatically selects the right Java version for your Gradle project
- Image hosting on a private Docker registry like Harbor
Prerequisites
To follow this guide, you should have:
- Docker installed on your system
https://www.maksonlee.com/install-docker-on-ubuntu-24-04/ - An existing Android project with a
gradlew
wrapper - Access to a Docker registry (e.g., Harbor)
https://www.maksonlee.com/install-harbor-2-13-1-on-ubuntu-24-04-with-haproxy-lets-encrypt-dns-01-and-systemd/
- Create the Dockerfile
Create a file named Dockerfile
:
FROM ubuntu:24.04
# Install dependencies
RUN apt-get update && apt-get install -y \
zip unzip curl \
&& rm -rf /var/lib/apt/lists/*
# Environment paths
ENV SDKMAN_DIR=/home/ubuntu/.sdkman
ENV ANDROID_HOME=/home/ubuntu/Android
ENV PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$SDKMAN_DIR/bin:$SDKMAN_DIR/candidates/java/current/bin:$PATH
# Use bash so we can use su -c with login shell behavior
SHELL ["/bin/bash", "-c"]
# Install SDKMAN and Java
RUN su - ubuntu -c "\
curl -s https://get.sdkman.io | bash && \
source ~/.sdkman/bin/sdkman-init.sh && \
sdk install java 8.0.452-tem && \
sdk install java 11.0.27-tem && \
sdk install java 17.0.15-tem && \
sdk install java 21.0.7-tem \
"
# Install Android command-line tools
RUN su - ubuntu -c "\
mkdir -p ~/Android/cmdline-tools && \
cd ~/Android && \
curl -OL https://dl.google.com/android/repository/commandlinetools-linux-13114758_latest.zip && \
unzip commandlinetools-linux-13114758_latest.zip -d cmdline-tools && \
mv cmdline-tools/cmdline-tools cmdline-tools/latest && \
rm commandlinetools-linux-13114758_latest.zip && \
source ~/.sdkman/bin/sdkman-init.sh && \
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses \
"
COPY setup-java-from-gradle.sh /home/ubuntu/setup-java-from-gradle.sh
RUN su - ubuntu -c "mkdir ~/.gradle"
WORKDIR /workspace
- Add the Java Detection Script
Save the following script as setup-java-from-gradle.sh
in the same directory:
#!/bin/bash
JAVA_VERSIONS=(
"8.0.452-tem"
"11.0.27-tem"
"17.0.15-tem"
"21.0.7-tem"
)
GRADLEW="./gradlew"
TEST_CMD="$GRADLEW help"
echo "🔍 Scanning for the first compatible Java version..."
for version in "${JAVA_VERSIONS[@]}"; do
echo -e "\n🧪 Trying Java $version ..."
sdk use java "$version" >/dev/null
java -version
if $TEST_CMD &>/dev/null; then
echo "✅ Java $version is compatible with Gradle!"
echo "🎯 Selected Java version: $version"
return 0
else
echo "❌ Java $version is NOT compatible."
fi
done
echo -e "\n❌ No compatible Java version found."
return 1
You don’t need to chmod +x
this script, because it will be sourced.
- Build the Docker Image
Build the Docker image and tag it for your private registry:
docker build -t harbor.maksonlee.com/library/android-build-env .
Push it to Harbor:
docker login harbor.maksonlee.com
docker push harbor.maksonlee.com/library/android-build-env
- Build Your App in the Container
Navigate to your Android project folder, then run:
docker run \
-u $(id -u):$(id -g) \
-v gradle-cache:/home/ubuntu/.gradle \
-v android-sdk:/home/ubuntu/Android \
-v "$PWD:/workspace" \
-it harbor.maksonlee.com/library/android-build-env \
/bin/bash
Once inside the container, run:
source ~/setup-java-from-gradle.sh
./gradlew assembleDebug # or ./gradlew assembleRelease
How It Works
- Java compatibility is automatically resolved using
sdk use
and Gradle help. - The Gradle and Android SDK cache are mounted with named Docker volumes.
- You don’t need to install anything Android-related on your host.
- You can reuse this image in CI systems like Jenkins, GitHub Actions, or GitLab CI.
Conclusion
With this Docker setup, building Android apps becomes repeatable, isolated, and platform-independent. You can now:
- Avoid Java/Gradle version conflicts
- Simplify Android SDK management
- Standardize builds across team members or automation systems