This page looks best with JavaScript enabled

Alpine Android

🐋 Small docker image for building & testing Android applications

 ·   ·  ☕ 12 minutes read

Description

Alpine Android is a lightweight Docker image for compiling and testing Android applications. Based on Alpine’s image, it makes the size smaller compared to Debian or Ubuntu based images. Also, there are different images per SDK and only the minimum packages are included.

SDK versions from Android 21 to Android 30 are available. Each version of the SDK has its own image, being the identifier alvrme/alpine-android:android-<version>. If you always want to refer to the latest stable Android version available, you can also use alvrme/alpine-android:latest.

Note that when version 31 of the SDK is released, if you want to continue using version 30, it is better to use the version tag.

Alpine Android Base

There are two versions available to extend from. The image based on AdoptOpenJDK8 Alpine with suffix -jdk8 and the image based on AdoptOpenJDK11 Alpine with suffix -jdk11. The version with Java 11 is mandatory if you use a version of Android Gradle Plugin equal to or greater than 7.0.0. Both versions contain the basic and necessary tools to compile and test any Android application or library whose compileSdkVersion is between version 21 (Android 5 / Lollipop) and version 30 (Android 11).

This makes it easy to update the images that extend from it, since only the necessary Dockerfile would have to be modified.

Use as base image

To extend the base image and be able to configure your own image with the packages and applications you want, just add the following line to the top of Dockerfile:

1
FROM alvrme/alpine-android-base

Install applications and packages

You can install any Alpine application from the following list by adding the following command to the `Dockerfile

1
2
RUN apk add --no-cache <package1> <package2> <...> && \
    rm -rf /tmp/* /var/tmp/*

Similarly, you can install any available package of Android:

1
RUN sdkmanager --sdk_root=${ANDROID_SDK_ROOT} --install <package1> <package2> <...>

Variants

There are two variants of the image:

  • JDK8 images are based on adoptopenjdk/openjdk8:alpine (JDK 8u292-b10) and uses the tag’s suffix -jdk8.
  • JDK11 images are based on adoptopenjdk/openjdk11:alpine (JDK 11.0.11+9) and uses the tag’s suffix -jdk11.

Which one should I use?

The recommended version is JDK8 if you are not using AGP v7.0.0+ or you are using DataBinding with a version of AGP prior to v7.0.0. Otherwise you must use JDK11 version because AGP v7.0.0+ will only work with version 11+ of the JDK.

If you want to use a JDK11 image with a version of AGP prior to v7, remember that JAXB is not included and you must add the following dependencies if using DataBinding:

1
implementation "org.glassfish.jaxb:jaxb-runtime:2.3.3"
1
implementation("org.glassfish.jaxb:jaxb-runtime:2.3.3")

Tagging

APIJDK8JDK11
Base imagejdk8, latest, latest-jdk8jdk11, latest-jdk11
Android 5.0 (21)android-21, android-21-jdk8android-21-jdk11
Android 5.1 (22)android-22, android-22-jdk8android-22-jdk11
Android 6.0 (23)android-23, android-23-jdk8android-23-jdk11
Android 7.0 (24)android-24, android-24-jdk8android-24-jdk11
Android 7.1 (25)android-25, android-25-jdk8android-25-jdk11
Android 8.0 (26)android-26, android-26-jdk8android-26-jdk11
Android 8.1 (27)android-27, android-27-jdk8android-27-jdk11
Android 9.0 (28)android-28, android-28-jdk8android-28-jdk11
Android 10 (29)android-29, android-29-jdk8android-29-jdk11
Android 11 (30)android-30, android-30-jdk8, latest, latest-jdk8android-30-jdk11, latest-jdk11
Android 12 (31)android-S, android-S-jdk8android-S-jdk11

📝 The tags latest and android-XX will be using the JDK8 base image for one year after AGP 7.0.0 is released to avoid problems with currents CI/CD configurations. That date is yet TBD. After that date, if you want to continue to use JDK8, you must update your configuration with the corresponding tag.

⚠️ Android 12 is in beta state. Preview versions are tagged differently using the letter of the version instead the API level. Android 12 will be using latest tag one month and a half after the stable release (TBD).

Versioning

Since January 1st 2021, new versions now include the date it was published so is possible to revert to a previous version. The versioning only applies to tags with the JDK version specified. The tag’s format is: android-XX-jdkZZ-vYYYY.MM.DD, where:

  • XX is the API level.
  • ZZ is the version of the JDK.
  • YYYY is the year of the release version.
  • MM is the month of the year of the release version with leading zeros.
  • DD is the day of the month of the release version with leading zeros.

A valid example would be android-30-jdk11-v2021.01.01. Here are listed all the versions.

📝 The versioning is not available for alpine-android-base.

Tools included

Below is a list of all the tools included with the installation of the different packages. Those with their own documentation are linked.

The gradle package is not installed, so the command in the PATH is not available. The reason for this is that the package may be outdated and not compatible with any of the APIs used in the configuration. That’s why you should always use the wrapper that comes with the project and whose version is indicated in the gradle-wrapper.properties file. You can consult here how to configure the wrapper to use it in the different CI/CD services.

Command-line

  • apkanalyzer: Provides insight into the composition of your APK after the build process completes.
  • avdmanager: Allows you to create and manage Android Virtual Devices (AVDs) from the command line.
  • lint: A code scanning tool that can help you to identify and correct problems with the structural quality of your code.
  • screenshot2: Do a screenshot of the running emulator.
  • sdkmanager: Allows you to view, install, update, and uninstall packages for the Android SDK.

SDK build

  • aapt2: Parses, indexes, and compiles Android resources into a binary format that is optimized for the Android platform, and packages the compiled resources into a single output.
  • apksigner: Signs APKs and checks whether APK signatures will be verified successfully on all platform versions that a given APK supports.
  • zipalign: Optimizes APK files by ensuring that all uncompressed data starts with a particular alignment relative to the start of the file.

SDK platform

  • adb: Android Debug Bridge (adb) is a versatile tool that lets you manage the state of an emulator instance or Android-powered device. You can also use it to install an APK on a device.
  • etc1tool: A command line utility that lets you encode PNG images to the ETC1 compression standard and decode ETC1 compressed images back to PNG.
  • fastboot: Flashes a device with platform and other system images.
  • logcat: This is a tool invoked via adb to view app and system logs.

Other tools

  • ia: Check and run an instant application.

In addition to the above Android-specific tools, the BusyBox commands and packages installed on the base image are also available:

  • git
  • unzip
  • wget

Extras

The base image also includes the extras command that contains small utilities that are not installed by default, since their use is not widespread.

These extras are executed with the command extras <command> and are the following

Fastlane

fastlane is a tool for iOS and Android developers to automate tedious tasks like generating screenshots, dealing with provisioning profiles, and releasing your application. Visit their documentation for more information.

This command allows you to install fastlane. There are two variants:

1
extras fastlane

This command allows you to install the latest version of fastlane. If you want to use a specific version, the command is as follows:

1
extras fastlane <version>

Content of each image

PathVersionDescriptionLocation
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
PathVersionDescriptionLocation
build-tools;21.1.221.1.2Android SDK Build-Toolsbuild-tools/21.1.2/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-212Android SDK Platform 21platforms/android-21/
PathVersionDescriptionLocation
build-tools;22.0.122.0.1Android SDK Build-Toolsbuild-tools/22.0.1/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-222Android SDK Platform 22platforms/android-22/
PathVersionDescriptionLocation
build-tools;23.0.323.0.3Android SDK Build-Toolsbuild-tools/23.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-233Android SDK Platform 23platforms/android-23/
PathVersionDescriptionLocation
build-tools;24.0.324.0.3Android SDK Build-Toolsbuild-tools/24.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-242Android SDK Platform 24platforms/android-24/
PathVersionDescriptionLocation
build-tools;25.0.325.0.3Android SDK Build-Toolsbuild-tools/25.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-253Android SDK Platform 25platforms/android-25/
PathVersionDescriptionLocation
build-tools;26.0.326.0.3Android SDK Build-Toolsbuild-tools/26.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-262Android SDK Platform 26platforms/android-26/
PathVersionDescriptionLocation
build-tools;27.0.327.0.3Android SDK Build-Toolsbuild-tools/27.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-273Android SDK Platform 27platforms/android-27/
PathVersionDescriptionLocation
build-tools;28.0.328.0.3Android SDK Build-Toolsbuild-tools/28.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-286Android SDK Platform 28platforms/android-28/
PathVersionDescriptionLocation
build-tools;29.0.329.0.3Android SDK Build-Toolsbuild-tools/29.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-295Android SDK Platform 29platforms/android-29/
PathVersionDescriptionLocation
build-tools;30.0.330.0.3Android SDK Build-Toolsbuild-tools/30.0.3/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-303Android SDK Platform 30platforms/android-30/
PathVersionDescriptionLocation
build-tools;31.0.0-rc431.0.0-rc4Android SDK Build-Toolsbuild-tools/31.0.0-rc4/
extras;google;instantapps1.9.0Google Play Instant Development SDKextras/google/instantapps/
patcher;v41SDK Patch Applier v4patcher/v4/
platform-tools31.0.2Android SDK Platform-Toolsplatform-tools/
platforms;android-S4Android SDK Platform S (Preview)platforms/android-S/

Container registries

Because of the DockerHub rate limits, the image is now in three different containers registries:

As base image

Replace <tag> with one of the current available tags.

DockerHub’s base image

You can use the Docker images from DockerHub as a base image for creating a new one:

1
FROM alvrme/alpine-android-base:<tag>
1
FROM alvrme/alpine-android:<tag>

GHCR’s base image

You can use the Docker images from GitHub Container Registry as a base image for creating a new one:

1
FROM ghcr.io/alvr/alpine-android-base:<tag>
1
FROM ghcr.io/alvr/alpine-android:<tag>

Quay’s base image

You can use the Docker images from Quay as a base image for creating a new one:

1
FROM quay.io/alvr/alpine-android-base:<tag>
1
FROM quay.io/alvr/alpine-android:<tag>

Pulling

Replace <tag> with one of the current available tags.

DockerHub pulling

You can pull a specific Docker image from DockerHub with the following command:

1
docker pull alvrme/alpine-android-base:<tag>
1
docker pull alvrme/alpine-android:<tag>

GHCR pulling

You can pull a specific Docker image from GitHub Container Registry with the following command:

1
docker pull ghcr.io/alvr/alpine-android-base:<tag>
1
docker pull ghcr.io/alvr/alpine-android:<tag>

Quay pulling

You can pull a specific Docker image from Quay with the following command:

1
docker pull quay.io/alvr/alpine-android-base:<tag>
1
docker pull quay.io/alvr/alpine-android:<tag>

Run container

Replace <tag> with one of the current available tags.

The command below will create a new container based on the specific image. It will open in the /home/android directory and the various available commands in the PATH will be able to be executed. Once the container is closed, it will be deleted. To keep the container after closing it, you have to remove --rm from the command.

DockerHub run container

Run the container from the DockerHub image:

1
docker run --rm -it alvrme/alpine-android-base:<tag>
1
docker run --rm -it alvrme/alpine-android:<tag>

GHCR run container

Run the container from the GitHub Container Registry image:

1
docker run --rm -it ghcr.io/alvr/alpine-android-base:<tag>
1
docker run --rm -it ghcr.io/alvr/alpine-android:<tag>

Quay run container

Run the container from the Quay image:

1
docker run --rm -it quay.io/alvr/alpine-android-base:<tag>
1
docker run --rm -it quay.io/alvr/alpine-android:<tag>

Use in different CI/CD

Here are different configurations for some of the available CI/CD services. Before you start, remember that you must use Gradle’s wrapper and it needs execution permissions. To give execution permissions to an executable, add chmod +x ./gradlew to the steps, or use git update-index --chmod=+x ./gradlew in the repository and then push the changes. This way, you don’t have to give permissions every time.

CircleCI

An example of CircleCI configuration. For more information, visit the official documentation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
version: 2
jobs:
  build:
    docker:
      - image: alvrme/alpine-android:android-30
    environment:
      JVM_OPTS: -Xmx3200m
    steps:
      - checkout
      - restore_cache:
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "app/build.gradle" }}
      - run: # Can omit if used `git update-index --chmod=+x ./gradlew` before.
         name: Chmod
         command: chmod +x ./gradlew
      - run:
          name: Download dependencies
          command: ./gradlew androidDependencies
      - save_cache:
          paths:
            - ~/.gradle
          key: jars-{{ checksum "build.gradle" }}-{{ checksum  "app/build.gradle" }}
      - run:
          name: Compile
          command: ./gradlew build
      - run:
          name: Testing
          command: ./gradlew lint test
      - run:
          name: Assemble
          command: |
            ./gradlew assembleRelease
            apksigner sign --ks keystore.jks --ks-key-alias <alias> --ks-pass pass:<keystore-pass> --key-pass pass:<alias-pass> app.apk # Passwords in plain
            apksigner sign --ks keystore.jks --ks-key-alias <alias> --ks-pass env:<keystore-pass> --key-pass env:<alias-pass> app.apk # Passwords in envvar            

GitHub

An example of GitHub Actions configuration. For more information, visit the official documentation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
jobs:
  build:
    container:
      image: alvrme/alpine-android:android-30

    steps:
      - uses: actions/[email protected]
      - name: Chmod # Can omit if used `git update-index --chmod=+x ./gradlew` before.
        run: chmod +x ./gradlew
      - uses: actions/[email protected]
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper            
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
          restore-keys: |
                        ${{ runner.os }}-gradle-
      - name: Download dependencies
        run: ./gradlew androidDependencies
      - name: Build
        run: ./gradlew build
      - name: Testing
        run: ./gradlew lint test
      - name: Assemble
        run: |
          ./gradlew assembleRelease
          apksigner sign --ks keystore.jks --ks-key-alias <alias> --ks-pass pass:<keystore-pass> --key-pass pass:<alias-pass> app.apk # Passwords in plain
          apksigner sign --ks keystore.jks --ks-key-alias <alias> --ks-pass env:<keystore-pass> --key-pass env:<alias-pass> app.apk # Passwords in envvar          

GitLab

An example of GitLab CI/CD configuration. For more information, visit the official documentation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
image: alvrme/alpine-android:android-30

before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle
  - chmod +x ./gradlew # Can omit if used `git update-index --chmod=+x ./gradlew` before.

cache:
  key: "$CI_COMMIT_REF_NAME" # Optional: share cache between branches
  paths:
     - .gradle/wrapper
     - .gradle/caches

stages:
  - build
  - test
  - assemble

build:
  stage: build
  script:
    - ./gradlew build

tests:
  stage: test
  script:
    - ./gradlew lint test

assemble:
  stage: assemble
  script:
    - ./gradlew assembleRelease
    - apksigner sign --ks keystore.jks --ks-key-alias <alias> --ks-pass pass:<keystore-pass> --key-pass pass:<alias-pass> app.apk # Passwords in plain
    - apksigner sign --ks keystore.jks --ks-key-alias <alias> --ks-pass env:<keystore-pass> --key-pass env:<alias-pass> app.apk # Passwords in envvar

Statistics

dockeri.co
dockeri.co

GitHub

Docker Alpine Android
Docker Alpine Android Base

Share on
Support the author with