Self-hosted service
google/android-emulator-container-scripts avatar
google/android-emulator-container-scripts

android-emulator-container-scripts: Google's tooling for running Android Emulator in Docker

This is a set of minimal scripts to run the emulator in a container for various systems such as Docker, for external consumption

2,098 stars293 forksPythonApache-2.0

At a glance

What is it?
android-emulator-container-scripts is a Python-based toolkit from Google for running the Android Emulator in Docker containers on Linux. It handles container image creation, ADB connectivity, GPU acceleration, and WebRTC browser streaming, with KVM on the host as a hard requirement.
Who is it for?
android-emulator-container-scripts suits teams running Android CI on Linux with KVM access or on cloud instances that support nested virtualization. The README's experimental label aligns with version 0.1.0 in pyproject.toml.
Can I use it commercially?
Yes. Apache-2.0 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 6 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

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

Editorial analysis

Running Android Emulator in a container for CI and remote testing

The project provides a Python CLI and a set of Docker helpers for running the Android Emulator in a container on Linux. The driving use case is Android testing in CI pipelines where a physical device or a local emulator is impractical, particularly on remote servers or cloud VMs. The repository is from Google and carries an explicit experimental label in the README, which advises installing it in a Python virtual environment and filing issues when things are not working as expected.

The `emu-docker` CLI handles the full lifecycle: listing available system images, downloading zip archives from Google's Android SDK servers, generating Dockerfiles, building images, and starting containers. A separate path uses pre-built images hosted by Google in Artifact Registry, which removes the download and build step entirely. Both paths require KVM on the host.

Python 3.10 or newer is required, along with `python3-venv` for virtual environment creation, ADB on the system PATH, and Docker Engine configured for non-root use. Docker Compose, either the `docker compose` plugin (v2) or the legacy `docker-compose` (v1), is also a stated dependency. The project is Apache-2.0 licensed.

KVM access is the constraint that determines where this runs

KVM must be available as /dev/kvm on the host. Three cloud provider paths appear in the README for obtaining KVM access: AWS bare-metal instances or instance types that explicitly support KVM; Azure VM sizes supporting nested virtualization, such as the Dv3 and Ev3 series; and Google Compute Engine VMs with nested virtualization enabled.

The README adds a warning: reduced performance should be expected when using nested virtualization. Running on a bare-metal AWS instance avoids that penalty; running on a general-purpose cloud VM that supports nested virtualization does not.

Container images have been tested under Debian and Ubuntu. Docker Desktop on macOS and Windows is explicitly named in the README as not supported for KVM acceleration. This is a harder boundary than simply "runs on Linux": teams using Docker Desktop on macOS for local development cannot substitute it for the Linux KVM path. Anyone who needs to run Android Emulator tests on a macOS developer machine would need a different approach entirely, one the README does not document.

The requirements section lists `python3-venv` as a necessary part of the Python installation. ADB must be on the system PATH, either through the full Android SDK Platform-Tools or the command-line tools package. Teams on general-purpose cloud VM types that do not explicitly list nested virtualization support will need to switch to a compatible instance type before the emulator will start. TROUBLESHOOTING.md in the repository is the first place to check when KVM access is unclear.

Using pre-built images from Google Artifact Registry without building anything

The fastest setup path skips building entirely. Google hosts pre-built container images at a public Google Artifact Registry. To run an Android 30 image with Google APIs on x64, the README gives this command:

sh
docker run \
  -e ADBKEY="$(cat ~/.android/adbkey)" \
  --device /dev/kvm \
  --publish 8554:8554/tcp \
  --publish 5555:5555/tcp \
  us-docker.pkg.dev/android-emulator-268719/images/30-google-x64:30.1.2

Port 5555 carries ADB and port 8554 carries the web and WebRTC interface. Once the container is running, connect with:

sh
adb connect localhost:5555

The expected output from `adb devices` after connecting is `localhost:5555 device`. In automated scripts, the README shows running the container in detached mode with the -d flag, then calling `adb wait-for-device` to block until the emulator finishes booting. The file `run-in-script-example.sh` contains a more complete scripted example. Full details on which pre-built images are available appear in REGISTRY.MD.

The `ADBKEY` environment variable takes the content of the private ADB key file, not a path to it. The `$(cat ~/.android/adbkey)` expansion in the command reads the key into the variable at container start time.

Installing emu-docker and building a custom image

For control over the system image and emulator version, the `emu-docker` CLI handles the build process. Install it with:

sh
source ./configure.sh

This script creates or activates a Python virtual environment and installs `emu-docker` into it. For guided image creation, the interactive mode prompts for a system image and emulator version, then handles the download and build:

sh
emu-docker interactive --start

To inspect what is available before building, `emu-docker list` prints the published system images and emulator builds, with the API level, variant, architecture and download URL for each entry. Building manually requires two steps after downloading the zip files:

sh
emu-docker create <emulator-zip> <system-image-zip> [--dest docker-src-dir]

Then build the Docker image from the generated directory:

sh
docker build <docker-src-dir>

The `--dest` flag sets the directory where the generated Dockerfile and supporting files land. Once built, the image can be run with `run.sh <docker-image-id> <additional-emulator-params>` or directly via `docker run` with the `--device /dev/kvm` and `--publish` flags.

To build and push directly to a registry in one step, the command takes a `--push` and `--repo` flag:

sh
emu-docker -v create --push --repo us.gcr.io/emulator-project/ stable "U"

API levels, emulator tracks, and the ps16k page-size variant for API 35

The `emu-docker list` output in the README shows entries for API levels 30, 31, 33, 34 and 35, covering the `google_apis` and `google_apis_playstore` variants on x86_64. Two emulator versions appear: stable at 36.5.11 and dev at 36.6.8. The dev track carries a higher build number and is listed separately.

One entry in the list warrants attention. API 35 has two x86_64 lines rather than one. The second carries `ps16k` in the URL path, which the README annotates as indicating a 16 KB page-size variant. A container built from the standard API 35 image and one built from the `ps16k` variant produce containers with different kernel memory page sizes. The distinction only matters for apps or system-level code that touches memory-mapped files or OS page size assumptions; for most testing purposes the standard image is correct.

The naming convention for images pushed to a registry is `{api}-{sort}-{abi}`, with an emulator version as the tag. For example, `34-playstore-x64:36.5.11` identifies API 34, the Play Store variant, on x64, built with emulator 36.5.11.

GPU acceleration and WebRTC browser streaming

GPU acceleration requires NVIDIA hardware and the NVIDIA Container Toolkit installed on the host. An Xvfb X server must be running if the setup is headless. To build a GPU-accelerated image, add the `--gpu` flag:

sh
emu-docker create stable U --gpu

Here `stable` picks the stable emulator track and `U` selects Android U (API 34). Running the result uses the provided helper script:

sh
./run-with-gpu.sh <docker-image-id> <additional-emulator-params>

The repository also provides an end-to-end WebRTC streaming architecture that lets a browser view and control the emulator without requiring external proxies like Envoy or a separate video bridge binary. The README calls this a React web client communicating over HTTP REST with a Python gateway, which connects to the emulator. The `create_web_container.sh` script and the gateway/ directory in the repository are part of this setup, and the web interface runs on port 8554.

The WebRTC path and the GPU path are independent. A team doing headless CI testing over ADB has no reason to set up WebRTC. The web streaming setup exists primarily for interactive use cases where a developer or test operator needs to see and interact with the emulator from a browser rather than through ADB tooling.

Experimental status, the tmpfs performance option, and the Linux-only constraint

The README labels the project experimental and explicitly asks users to file issues when things break. The pyproject.toml records version 0.1.0, and no tagged versions have been published on GitHub. The Python dependencies declared in pyproject.toml include PyYAML, docker, tqdm, console-menu, click, appdirs, colorlog, and Jinja2. Running the configure.sh script installs these into the virtual environment automatically. This aligns with the experimental framing: the project is usable in practice, but the interface and behavior may change.

One concrete performance option appears in the README: mounting a `/data` partition in tmpfs to improve disk performance. The command adds one flag to the standard `docker run` invocation:

sh
docker run -e ADBKEY="$(cat ~/.android/adbkey)" \
  --mount type=tmpfs,destination=/data \
  --publish 8554:8554/tcp \
  --publish 5555:5555/tcp <docker-image-id>

The trade-off is that `/data` sits in RAM rather than on the container's overlay filesystem, so any writes to that partition are lost when the container stops. For stateless test runs this is generally acceptable; for anything that needs to persist data across container restarts it is not.

Nested virtualization reduces performance, as the README warns. Running on bare-metal Linux hosts avoids that penalty. Docker Desktop on macOS and Windows does not support KVM acceleration, which rules out the two most common developer desktop platforms. The combination of Linux-only KVM and experimental status means this is a tool for dedicated CI infrastructure, not for casual local emulator use.

Editorial conclusion

android-emulator-container-scripts suits teams running Android CI on Linux with KVM access or on cloud instances that support nested virtualization. The README's experimental label aligns with version 0.1.0 in pyproject.toml. Teams expecting to run it on macOS or Windows with Docker Desktop will find KVM acceleration is not supported on those platforms. Before starting, confirm the host exposes /dev/kvm: on a cloud VM, check that nested virtualization is enabled. If it is available, the pre-built Google Artifact Registry images cut first setup to a single docker run command.

Frequently asked questions

How do I install android-emulator-container-scripts?

Run `source ./configure.sh` from the repository root. This creates a Python virtual environment, activates it, and installs the `emu-docker` CLI into it. Python 3.10 or newer is required.

Does android-emulator-container-scripts work on macOS or Windows?

No. The README explicitly states that Docker Desktop on macOS and Windows is not supported for KVM acceleration. The project runs on Linux only, either on bare-metal hosts or on cloud VMs with nested virtualization enabled.

How do I connect ADB to the Android Emulator container?

Run `adb connect localhost:5555` once the container is running. The ADB private key must be passed into the container through the `ADBKEY` environment variable. For automated scripts, use `adb wait-for-device` to block until the emulator finishes booting.

What Android API levels are available in the pre-built images?

The `emu-docker list` output shows entries for API levels 30, 31, 33, 34 and 35 for x86_64 under the google_apis and google_apis_playstore variants. API 35 has a second entry with a ps16k label for a 16 KB page-size variant.

Is android-emulator-container-scripts production-ready?

The README labels it experimental and recommends installing it in a Python virtual environment while filing issues for anything that is not working. The package version is 0.1.0 and there are no GitHub releases.

Official sources

  1. google/android-emulator-container-scripts on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
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/google-android-emulator-container-scripts.svg)](https://hysenlabs.com/projects/google-android-emulator-container-scripts)