DEV Community

Ai2th
Ai2th

Posted on

Pockr | Part 6 — Test Results and What's Next

Test Results, Firebase Test Lab, and What's Next for Pockr

Part 6 of 6 — the final chapter of building Pockr, a single APK that runs Docker on non-rooted Android.
← Part 5: Debugging a VM Restart Loop


Download

pockr-v1.apk — v1.0.0 · ARM64 · 163 MB
Release notes · GitHub

Requires Android 9+ (API 28), ARM64 device. Enable "Install from unknown sources" before installing.


How We Test: Firebase Test Lab

Physical device testing on a Mac with an Android emulator is unreliable for this project — QEMU needs hardware virtualisation, and nested virtualisation in emulators doesn't work.

Instead, every build gets tested on Firebase Test Lab with a Robo test:

Setting Value
Device Pixel 2 (arm64)
Android version 11 (API 30)
Test type Robo (automated UI crawler)
Timeout 600 seconds
Architecture ARM64 (same as real phones)

The Robo crawler explores the UI systematically — tapping every button it finds, navigating every screen, filling forms. It's brutal but effective at finding race conditions and edge cases that manual testing misses.


Test History

Version Result What Changed
v11–v20 ❌ Various crashes ELF/linker issues, asset extraction bugs
v22 ✅ Pass VmManager as Application singleton — QEMU survives Activity relaunch
v23 ✅ Pass DNS fix (use-vc + 8.8.8.8 fallback) — Docker Hub reachable
v24 ✅ Pass Flutter ScaffoldMessenger context fix
v25 ✅ Pass First container pull + run — busybox and nginx from Docker Hub (~78s)
v28 ✅ Pass Release APK + Pockr branding
v30 ✅ Pass Corrected APK filename in test script
v33 ✅ Pass Race condition fix in VmManager.getStatus() — no more restart loop
v34 ❌ Fail Double-start found — Robo tapped Start during starting→running transition, launching a second QEMU instance
v35 ✅ Pass Double-start guard in VmState.startVm() — confirmed no double-start, containers running

What a Passing Test Looks Like

From the v35 logcat (second boot — Docker image cache already warm):

03:38:02  VmManager: Starting VM...
03:38:02  VmManager: Reusing existing user.qcow2 (Docker image cache preserved)
03:38:02  VmManager: VM process launched

         ... Alpine second boot: ~50 seconds ...
         ... API server comes up ...

03:38:53  VmApiClient: Container started: alpine_1772710722409  ✅
03:39:28  VmApiClient: Container started: test_1772710762640    ✅
Enter fullscreen mode Exit fullscreen mode

From cold install (first boot, Docker + Python setup):

03:35:33  VmManager: Starting VM...
03:35:33  VmManager: Extracted vm/base.qcow2 (fresh install)
03:35:33  VmManager: VM process launched

         ... Alpine first boot: ~2–5 minutes ...
         ... Docker installs, API server bootstraps ...
Enter fullscreen mode Exit fullscreen mode

From cold install to running container: ~5 minutes.
Second boot (Docker image cache warm): ~50 seconds.


What Works Today

  • ✅ Install APK → tap Start → QEMU boots Alpine Linux
  • ✅ Docker pulls images from Docker Hub over SLIRP networking
  • busybox, alpine, nginx confirmed running on real hardware (ARM64, Android 11)
  • ✅ Persistent overlay disk — pulled images survive VM restarts
  • ✅ No root. No Termux. No PC required after install.
  • ✅ Foreground service keeps VM alive when app is backgrounded
  • ✅ Auto-start option to launch VM on app open

Current Limitations

Limitation Notes
First boot ~5 min Docker + Python bootstrap on Alpine; subsequent boots ~50s
ARM64 only QEMU binary targets aarch64 only (no ARM32/x86)
Storage driver: vfs Less efficient than overlay2, but works without kernel modules
--network host only No isolated container networks without bridge module
APK size ~163 MB Includes full Alpine disk image + QEMU binary + 50 libraries

What's Next

  • [ ] Stop container / view logs in app UI
  • [ ] ARM32 device support
  • [ ] Reduce first-boot time
  • [ ] Custom container image support from UI

The Full Series

  1. Part 1: The Idea and Architecture
  2. Part 2: Executing Binaries on Android — The SELinux Problem
  3. Part 3: Bundling 50 Native Libraries Without Breaking the Android Linker
  4. Part 4: Making Docker Run Without iptables, bridge, or overlay2
  5. Part 5: Debugging a VM Restart Loop — A Race Condition in Kotlin
  6. Part 6: Test Results and What's Next ← you are here

Pockr Series — Docker in Your Pocket

Pockr = Pocket + Docker. A single Android APK that runs real Docker containers in your pocket — no root, no Termux, no PC required.

# Post Topic
📖 Intro What is Pockr? Start here
1 Part 1 The Idea and Architecture
2 Part 2 Executing Binaries — The SELinux Problem
3 Part 3 Bundling 50 Native Libraries
4 Part 4 Docker Without Kernel Modules
5 Part 5 Debugging the VM Restart Loop
6 Part 6 Test Results and What's Next

GitHub: github.com/AI2TH/Pockr

QA & Release Engineer: Kalvin Nathan
skalvinnathan@gmail.com · LinkedIn

Top comments (0)