This repository contains the Docker build files used to create a browser-accessible Android emulator environment. It is organized as a layered image stack:
vnc-base: a Debian/Xfce desktop image with TigerVNC and noVNC.emulator_cloud: an Android SDK, Android Emulator, and Appium image built on top ofvnc-base.
The resulting container exposes a remote Linux desktop over VNC/noVNC and runs Appium for Android automation.
.
|-- README.md
|-- build_dockerfile.py
|-- vnc/
| |-- config.yml
| |-- Dockerfile
| |-- Makefile
| `-- src/
| |-- common/
| | |-- install/
| | |-- scripts/
| | `-- xfce/
| `-- debian/
| |-- install/
| `-- icewm/
`-- android/
|-- Dockerfile
|-- Makefile
|-- emulator_base
`-- scripts/
Builds the reusable desktop base image from debian:11.
Included components:
- Xfce desktop environment
- TigerVNC server on port
5901 - noVNC web client on port
6901 - Chromium browser
- Locale, fonts, shell helpers, and non-root container user setup
The VNC startup script is vnc/src/common/scripts/vnc_startup.sh. It creates the VNC password file, starts noVNC, starts TigerVNC, launches the window manager, and keeps the container alive.
Default VNC settings:
| Variable | Default |
|---|---|
DISPLAY |
:1 |
VNC_PORT |
5901 |
NO_VNC_PORT |
6901 |
VNC_RESOLUTION |
1280x1024 |
VNC_COL_DEPTH |
24 |
CONFIG_FILE |
/home/fortinet/config.yml |
VNC_PW |
Optional runtime override |
VNC_VIEW_ONLY |
false |
The VNC password is read from vnc/config.yml at build time and copied into the image as /home/fortinet/config.yml:
vnc:
password: "change_me"Update this value before building an image, or override it at runtime with -e VNC_PW=<password>. If neither VNC_PW nor vnc.password is configured, the container exits during startup.
Builds the Android emulator automation image from vnc-base:latest.
Included components:
- OpenJDK 17
- Android SDK command-line tools
- Android Emulator
- Android platform tools
- Android API/system image packages
- Node.js, npm, Appium, and the Appium
uiautomator2driver - Desktop shortcuts for launching emulator profiles
The current android/Dockerfile installs Android 35 packages:
platforms;android-35build-tools;35.0.0system-images;android-35;google_apis;x86_64platform-tools
It creates an AVD named google_api, copies Android config into /home/fortinet/.android/, expects a snapshot directory at android/snapshot/api_1.0.36, and starts Appium by default:
appium --relaxed-security \
--default-capabilities '{"newCommandTimeout": "0"}' \
--log /home/fortinet/appium_log/appium.log \
--base-path /wd/hub \
--log-level debugandroid/emulator_base appears to be an alternate or older base Dockerfile for Android API 34 setup.
The Makefiles publish images to the internal registry 10.160.16.60/emulator-cloud.
Build the VNC base image:
cd vnc
make build_docker_imagePush the VNC base image:
cd vnc
make push_docker_imageBuild the Android emulator image:
cd android
make build_docker_imagePush the Android emulator image:
cd android
make push_docker_imageThe Android image Makefile pulls the base image before building:
BASE_IMAGE := 10.160.16.60/emulator-cloud/vnc-base:latest
DOCKER_IMAGE := 10.160.16.60/emulator-cloud/emulator_cloud:$(tag_name)Example VNC base container:
docker run --rm -it \
-p 5901:5901 \
-p 6901:6901 \
10.160.16.60/emulator-cloud/vnc-base:latestOpen the web desktop through noVNC:
http://localhost:6901/?password=<configured-password>
Example Android emulator/Appium container:
docker run --rm -it \
-p 5901:5901 \
-p 6901:6901 \
-p 4723:4723 \
10.160.16.60/emulator-cloud/emulator_cloud:<tag>The Appium endpoint is available under:
http://localhost:4723/wd/hub
Depending on host configuration, Android emulator acceleration may require KVM/device access when running on Linux.
Image tags are intended to encode both image version and Android API level. The existing convention is:
<major>.<patch>.<api-level>
Example:
1.0.34
Meaning:
1: first major version of this image family0: no patch-level image changes34: Android API level
Check android/Makefile and android/Dockerfile together before releasing a new image. At the time of this README update, android/Makefile uses tag_name := 1.0.34, while android/Dockerfile installs Android 35 packages and references snapshot/api_1.0.36.
build_dockerfile.py: generates a separateemulator_docker_snapshot_readysample Docker project and zip archive for a prebuilt Android 34 snapshot workflow.android/scripts/start_google_api.sh: launches thegoogle_apiAVD from the remote desktop.android/scripts/start_android_api.sh: launches anandroid_apiAVD from the remote desktop, although the current Dockerfile createsgoogle_api.vnc/src/common/scripts/chrome-init.sh: prepares Chromium startup settings based on the VNC environment.vnc/src/common/scripts/generate_container_user: configuresnss_wrapperfor arbitrary non-root container users.
- noVNC:
http://<host>:6901/?password=<VNC_PW> - Native VNC:
<host>:5901 - VNC password source:
VNC_PWruntime environment variable, orvnc.passwordfrom/home/fortinet/config.yml - Default container user: UID
1000 - Appium logs:
/home/fortinet/appium_log/appium.log - Internal image builder noted by the original README: Jenkins host
10.160.50.118 - Internal registry noted by the original README:
10.160.16.60
Before publishing a new Android image:
- Confirm the Android API level in
android/Dockerfile. - Confirm
tag_nameinandroid/Makefilematches the intended release/versioning convention. - Confirm any referenced snapshot directory exists under
android/snapshot/. - Confirm
vnc/config.ymlhas the intended VNC password for the image being released. - Build and run the VNC base image if its scripts changed.
- Build and run the Android image, then verify:
- noVNC login works.
- Appium starts and listens on port
4723. - The expected AVD can be launched.
- Appium can create a session against the emulator.