# docker-android: Running the Android Emulator as a Docker Service

> docker-android packages the Android emulator inside an Alpine-based Docker container with KVM acceleration and ADB port-forwarding, making headless Android testing available to CI pipelines without a graphical desktop.

**HQarroum/docker-android** — 🤖 A minimal and customizable Docker image running the Android emulator as a service.

- Repository: https://github.com/HQarroum/docker-android
- Stars: 7,289 · Forks: 564
- Language: Shell
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/hqarroum-docker-android

## What docker-android Solves and Who Should Use It

Testing Android applications on physical devices in a CI environment is expensive. Running the standard Android emulator on a developer laptop blocks the machine and does not transfer cleanly into automated pipelines. docker-android addresses this by packaging the Android emulator, an ADB server, and QEMU with libvirt support into a Docker image that exposes the emulator as a network service.

The project targets engineers who need a reproducible, headless Android runtime in a containerized infrastructure. A CI agent that needs to install an APK, run UI tests, or exercise ADB commands can connect to the container over the network without any graphical setup. The README describes the focus as providing "a size-optimized Docker image bundled with the minimal amount of software required to expose a fully functioning Android emulator that's remotely controllable over the network."

The image is built on Alpine Linux and bundles Java Runtime Environment 11. Pre-built images are published to Docker Hub under the tag format api-{level}, so teams can pull a known Android version without building locally.

## Architecture: QEMU, KVM, and the ADB Bridge

The container runs the Android emulator using QEMU with KVM hardware virtualization. KVM offloads CPU emulation to the host kernel, which is the reason a Linux host with /dev/kvm exposed to the container is required. Without KVM, the emulator either refuses to start or runs at unusable speed.

Inside the container, an ADB server starts automatically and listens on all network interfaces. Port 5554 carries the emulator console and port 5555 carries ADB. These ports are forwarded out of the container so that tools running on the Docker host or elsewhere in the CI network can connect by address.

Emulator images are wiped each time the container restarts. This is a deliberate design choice for CI use: each test run starts from a clean Android system image. For scenarios where persistent storage is needed between runs, the entire AVD directory (/data inside the container, named android) can be mounted from a host path.

The image also exposes two Dockerfile variants. The standard Dockerfile uses the eclipse-temurin base, and Dockerfile.gpu adds NVIDIA GPU acceleration support for the emulator's graphics pipeline, useful when running instrumented UI tests that exercise the renderer.

## Installation and First Run

The fastest path to a running emulator uses the pre-built image from Docker Hub. Pull an API 33 image with:

```bash
docker pull halimqarroum/docker-android:api-33
```

Then start the container, mounting the KVM device and exposing ADB:

```bash
docker run -it --rm --device /dev/kvm -p 5555:5555 android-emulator
```

The emulator takes a minute or two to boot the Android kernel. Once the kernel is running, connect ADB from the host:

```bash
adb connect 127.0.0.1:5555
```

For teams using docker-compose, the repository ships a docker-compose.yml. Start the default service with:

```bash
docker compose up android-emulator
```

The docker-compose configuration sets API_LEVEL=34, MEMORY=16384, and CORES=16 by default, and mounts ADB key files from the ./keys directory. If you need a Google Play Store image, you first generate an ADB key pair with `adb keygen adbkey`, place adbkey and adbkey.pub in ./keys/, then start the cuda-store service.

To persist emulator storage across container restarts, mount the AVD volume:

```bash
docker run -it --rm --device /dev/kvm -p 5555:5555 -v ~/android_avd:/data android-emulator
```

After connecting ADB, you can use scrcpy to view and control the emulator screen remotely. The emulator defaults to a Pixel preset at 1080x1920:

```bash
scrcpy
```

## Customizing API Level, Image Type, and Architecture at Build Time

When the pre-built images do not match the required configuration, you build locally from the Dockerfile. Three build arguments control what Android system image is installed.

API_LEVEL sets the Android API level. IMG_TYPE selects the system image variant: google_apis for the standard image with Google APIs, or google_apis_playstore for an image that includes the Google Play Store. ARCHITECTURE selects the CPU architecture of the Android image. The README states that only x86_64 and x86 are actively supported.

For example, to build an Android Pie (API 28) image with Play Store support for 32-bit x86:

```bash
docker build \
  --build-arg API_LEVEL=28 \
  --build-arg IMG_TYPE=google_apis_playstore \
  --build-arg ARCHITECTURE=x86 \
  --tag android-emulator .
```

The default build uses API 33 with google_apis for x86_64. Switching API levels changes the image size considerably: the API 28 variant compresses to 1.46 GB, while API 33 reaches 1.97 GB compressed.

For CI pipelines that store the Android SDK on shared network storage such as NFS and want to reduce per-job build time, the SDK installation can be skipped at build time:

```bash
docker build -t android-emulator --build-arg INSTALL_ANDROID_SDK=0 .
```

The SDK directory must then be mounted at /opt/android when running the container:

```bash
docker run -it --rm --device /dev/kvm -p 5555:5555 -v /shared/android/sdk:/opt/android/ android-emulator
```

At runtime, environment variables fine-tune the emulator. MEMORY sets the RAM allocated (default 8192 MB), CORES sets the CPU count (default 4), and EXTRA_FLAGS passes additional flags to the emulator binary (default "-no-metrics -no-audio -partition-size=8192").

## Limitations of This Approach

The most significant constraint is the KVM requirement. KVM is available on Linux hosts that expose the kernel module. It is not available in most cloud VM tiers that are themselves virtualized with a hypervisor that does not support nested virtualization. If /dev/kvm cannot be mounted, the emulator either fails to start or runs at a speed that makes testing impractical.

The project actively supports only x86_64 and x86 Android images. arm64 host machines are increasingly common in CI infrastructure, but the README explicitly notes that only those two architectures are actively maintained for the Android image itself. Running an x86_64 Android image on an arm64 host with QEMU emulation is slow.

The image sizes are large. API 33 with the emulator compresses to 1.97 GB; the API 28 variant is 1.46 GB compressed. In environments where each CI job pulls a fresh image, this adds meaningful transfer time and registry storage costs. The SDK-less base image compresses to 138 MB, but that variant requires mounting the SDK externally.

The project has no GitHub releases. Version tracking relies on Docker Hub tags. The README notes that the current version is 1.1.0 but there is no release history in the repository.

## Alternatives: alpine-android and budtmo/docker-android

The README names two alternatives directly. The alpine-android project (github.com/alvr/alpine-android) takes a different base image approach for Android CI, providing SDK tools without running a live emulator. It is a better fit when the CI pipeline only needs Android build tooling (compilation, linting, static analysis) and does not need to launch an emulator.

The docker-android project by budtmo (github.com/budtmo/docker-android) is the closest functional alternative. It also runs the Android emulator inside Docker, but adds a WebRTC interface for browser-based screen access. That approach is useful when developers need to view the emulator without installing scrcpy locally. The trade-off is a more complex image with additional browser streaming dependencies.

For teams that do not need Docker at all, Waydroid is a different category of tool: it runs a full Android environment using Linux kernel namespacing rather than QEMU/KVM emulation, which gives lower overhead on compatible Linux hosts but ties the Android environment to the host kernel version. docker-android is the better choice when portability across hosts and clean per-run isolation are the primary requirements.

## Maintenance Status and License

The repository is not archived. The last push was on 2026-05-07. The project is distributed under the MIT license, which allows use in commercial and open-source pipelines without restriction on redistribution.

The Dockerfile in the repository shows the base image as eclipse-temurin:25, indicating the image has been updated to a recent JDK release. GitHub Actions workflows are present in the repository for automated Docker image builds.

The repository has no formal GitHub releases, so there is no changelog to follow. Version 1.1.0 is noted in the README.

## Conclusion

docker-android fits CI pipelines on Linux servers where KVM is available and where teams need a disposable Android emulator without maintaining a full Android SDK installation. It is the wrong choice for macOS Docker Desktop users (the image does not support it), for arm64 server targets (only x86_64 and x86 are actively maintained), and for workflows that require persistent emulator state across container restarts without a mounted volume. Before adopting it, verify that your host kernel exposes /dev/kvm and that 4 GB of free memory is available per emulator instance, since the README sets that as the minimum for API 33.

## FAQ

### What is docker-android?

docker-android is a Docker image that runs the Android emulator as a networked service inside a container. It exposes ADB on port 5555 and the emulator console on port 5554, allowing CI pipelines and remote tools to connect to a running Android device without a graphical desktop.

### How do you install and use docker-android?

Pull a pre-built image from Docker Hub with `docker pull halimqarroum/docker-android:api-33`, then run it with `docker run -it --rm --device /dev/kvm -p 5555:5555 android-emulator`. Once the kernel boots, connect ADB on the host with `adb connect 127.0.0.1:5555`.

### How does docker-android compare to Waydroid?

docker-android uses QEMU and KVM to run the standard Android emulator inside a container, which requires a Linux host with /dev/kvm. Waydroid runs Android using Linux kernel namespacing, which avoids the QEMU layer and reduces overhead but ties the Android environment to the host kernel version. docker-android is the better fit for isolated per-run CI environments.

### How does docker-android compare to ReDroid?

ReDroid is a GPU-acceleratable Android container that uses Linux kernel namespacing rather than QEMU emulation. docker-android uses the standard Android emulator with QEMU/KVM, which means it does not require a custom Android kernel build but does require /dev/kvm on the host. The README does not document ReDroid directly.

### What are the alternatives to docker-android?

The README names two: alpine-android for build tooling without a live emulator, and the budtmo/docker-android project, which runs the Android emulator with an added WebRTC interface for browser-based screen access instead of scrcpy.

## Sources

- [HQarroum/docker-android on GitHub](https://github.com/HQarroum/docker-android)
- [Issues](https://github.com/HQarroum/docker-android/issues)
- [License: MIT](https://github.com/HQarroum/docker-android/blob/main/LICENSE)
- [README](https://github.com/HQarroum/docker-android/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/hqarroum-docker-android
