Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sickcodes/dock-droid
Docker Android - Run QEMU Android in a Docker! X11 Forwarding! CI/CD for Android!
https://github.com/sickcodes/dock-droid
android docker droid kvm linux qemu x86 x86-64
Last synced: 3 days ago
JSON representation
Docker Android - Run QEMU Android in a Docker! X11 Forwarding! CI/CD for Android!
- Host: GitHub
- URL: https://github.com/sickcodes/dock-droid
- Owner: sickcodes
- License: gpl-3.0
- Created: 2021-07-03T22:06:35.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2022-04-22T19:39:18.000Z (almost 3 years ago)
- Last Synced: 2025-01-15T10:44:04.692Z (10 days ago)
- Topics: android, docker, droid, kvm, linux, qemu, x86, x86-64
- Language: Dockerfile
- Homepage: https://hub.docker.com/r/sickcodes/dock-droid
- Size: 34.3 MB
- Stars: 1,124
- Watchers: 17
- Forks: 87
- Open Issues: 22
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
- awesome - sickcodes/dock-droid - Docker Android - Run QEMU Android in a Docker! X11 Forwarding! CI/CD for Android! (Dockerfile)
README
# Dock-Droid · [Follow @sickcodes on Twitter](https://twitter.com/sickcodes)
![Running Android x86 & Android ARM in a Docker container](/dock-droid-docker-android.png?raw=true "ANDROID KVM IN DOCKER CONTAINER")
Docker Android - Run QEMU Android x86 and Android ARM in a Docker! X11 Forwarding! CI/CD for Android!
## Capabilities
- Security Research of ARM apps on x86!
- ADB on port `:5555`
- Magisk, riru, LSPosed on Android x86
- SSH enabled (`localhost:50922`)
- SCRCPY enabled (`localhost:5555`)
- WebCam forwarding enabled (`/dev/video0`)
- Audio forwarding enabled (`/dev/snd`)
- GPU passthrough (`/dev/dri`)
- X11 forwarding is enabled
- runs on top of QEMU + KVM
- supports BlissOS, custom images, VDI files, any Android x86 image, Xvfb headless mode
- you can clone your container with `docker commit`## Author
This project is maintained by @sickcodes [Sick.Codes](https://sick.codes/). [(Twitter)](https://twitter.com/sickcodes)
Additional credits can be found here: https://github.com/sickcodes/dock-droid/blob/master/CREDITS.md
Epic thanks to [@BlissRoms](https://github.com/BlissRoms) who maintain absolutely incredible Android x86 images. If you love their images, consider donating to the project: [https://blissos.org/](https://blissos.org/)!
Special thanks to [@zhouziyang](https://github.com/zhouziyang) who maintains an even more native fork [Redroid](https://github.com/remote-android/redroid-doc)!
This project is heavily based on Docker-OSX: https://github.com/sickcodes/Docker-OSX
### Related:
- Next Generation Anbox Style LXC:[https://github.com/sickcodes/droid-native](https://github.com/sickcodes/droid-native)
- Android in a Docker using [BlissOS](https://blissos.org/):
[https://github.com/sickcodes/dock-droid](https://github.com/sickcodes/dock-droid)
- binder(fs) and ashmem for use in anbox related 5.7+ Kernel distribuitons (soon to be all):
[https://github.com/sickcodes/anbox-modules-dkms](https://github.com/sickcodes/anbox-modules-dkms)
### Requirements
- 4GB disk space for bare minimum installation
- virtualization should be enabled in your BIOS settings
- a kvm-capable host (not required, but slow otherwise)## Initial setup
Before you do anything else, you will need to turn on hardware virtualization in your BIOS. Precisely how will depend on your particular machine (and BIOS), but it should be straightforward.Then, you'll need QEMU and some other dependencies on your host:
```bash
# ARCH
sudo pacman -S qemu libvirt dnsmasq virt-manager bridge-utils flex bison iptables-nft edk2-ovmf# UBUNTU DEBIAN
sudo apt install qemu qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils virt-manager# CENTOS RHEL FEDORA
sudo yum install libvirt qemu-kvm
```Then, enable libvirt and load the KVM kernel module:
```bash
sudo systemctl enable --now libvirtd
sudo systemctl enable --now virtlogdecho 1 | sudo tee /sys/module/kvm/parameters/ignore_msrs
sudo modprobe kvm
```## Quick Start Dock-Droid
You can run the Live OS image, or install to disk.
Connect to the WiFi network called `VirtWifi`.
### BlissOS x86 Image [![https://img.shields.io/docker/image-size/sickcodes/dock-droid/latest?label=sickcodes%2Fdock-droid%3Alatest](https://img.shields.io/docker/image-size/sickcodes/dock-droid/latest?label=sickcodes%2Fdock-droid%3Alatest)](https://hub.docker.com/r/sickcodes/dock-droid/tags?page=1&ordering=last_updated)
```bash
docker run -it \
--device /dev/kvm \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
sickcodes/dock-droid:latest
```Headlessly (on a server, or locally)
```bash
docker run -it \
--device /dev/kvm \
-e EXTRA="-display none -vnc 0.0.0.0:99,password=on" \
-p 5555:5555 \
-p 5999:5999 \
sickcodes/dock-droid:latest
```
For headless, in the QEMU console, type `change vnc password user`And then connect on `localhost:5999`, or the server IP, or Docker IP.
### No Image (:naked) [![https://img.shields.io/docker/image-size/sickcodes/dock-droid/naked?label=sickcodes%2Fdock-droid%3Anaked](https://img.shields.io/docker/image-size/sickcodes/dock-droid/naked?label=sickcodes%2Fdock-droid%3Anaked)](https://hub.docker.com/r/sickcodes/dock-droid/tags?page=1&ordering=last_updated)
```bash
docker run -it \
--device /dev/kvm \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-v "${PWD}/android.qcow2:/home/arch/dock-droid/android.qcow2" \
-p 5555:5555 \
sickcodes/dock-droid:naked```
### Run without KVM (Work in Progress)
This will boot, but currently does not "work".
Change `CPU` to `Penryn`, which is normally `host`
Change `ENABLE_KVM`, which is normally `-enable-kvm`
Change `KVM`, which is normally `accel=kvm:tcg`Change `CPUID_FLAGS`, which is normally very long.
```
# use a spacebar in quotes
-e CPU=qemu64 \
-e ENABLE_KVM=' ' \
-e KVM=' ' \
-e CPUID_FLAGS=' ' \
```For example **(Work in Progress)**:
```bash
docker run -it \
-e CPU=Penryn \
-e ENABLE_KVM=' ' \
-e KVM=' ' \
-e CPUID_FLAGS=' ' \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
sickcodes/dock-droid:latest
```### Increase RAM
Increase RAM by adding this line: `-e RAM=10 \` for 10GB.
## Docker Virtual Machine WebCam
![Android WebCam Passthrough SPICE USBREDIR QEMU Android x86](/Android-WebCam-Passthrough-QEMU-Android-x86.png?raw=true "Android WebCam Passthrough SPICE USBREDIR QEMU Android x86")
Want to use your Laptop/USB WebCam and Audio too?
There are two options: **usb passthrough**, or **usb redirect (network)**.
`v4l2-ctl --list-devices`
`lsusb`
Find the `hostbus` and `hostaddr`:
```console
Bus 003 Device 003: ID 13d3:56a2 IMC Networks USB2.0 HD UVC WebCam
```
Would be `-device usb-host,hostbus=3,hostaddr=3`### Passthrough Android Camera over USB
```bash
docker run -it \
--device /dev/kvm \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
-e EXTRA='-device usb-host,hostbus=3,hostaddr=3' \
sickcodes/dock-droid:latest
```### Passthrough Android WebCam Camera over the Network!
```console
lsusb
# Bus 003 Device 003: ID 13d3:56a2 IMC Networks USB2.0 HD UVC WebCam
```Vendor ID is `13d3`
Product ID is `56a2`In one Terminal on host:
```bash
sudo usbredirserver -p 7700 13d3:56a2
```In another Terminal on host:
```bash
# 172.17.0.1 is the IP of the Docker Bridge, usually the host, but you can change this to anything.
PORT=7700
IP_ADDRESS=172.17.0.1docker run -it \
--device /dev/kvm \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
-e EXTRA="-chardev socket,id=usbredirchardev1,port=${PORT},host=${IP_ADDRESS} -device usb-redir,chardev=usbredirchardev1,id=usbredirdev1,bus=ehci.0,debug=4" \
sickcodes/dock-droid:latest
```### Android x86 Docker GPU & Hardware Acceleration
Currently in development by BlissOS team: mesa graphics card + OpenGL3.2.
Want to use SwiftShader acceleration?
```bash
docker run -it \
--privileged \
--device /dev/kvm \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
-p 50922:10022 \
--device=/dev/dri \
--group-add video \
-e EXTRA='-display sdl,gl=on' \
sickcodes/dock-droid:latest
```### Use your own image/naked version
```bash
# get container name from
docker ps -a# copy out the image
docker cp container_name:/home/arch/dock-droid/android.qcow2 .
```Use any generic ISO or use your own Android AOSP raw image or qcow2
Where, `"${PWD}/disk.qcow2"` is your image in the host system.
```bash
docker run -it \
-v "${PWD}/android.qcow2:/home/arch/dock-droid/android.qcow2" \
--privileged \
--device /dev/kvm \
--device /dev/video0 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
-p 50922:10022 \
-e EXTRA='-device usb-host,hostbus=3,hostaddr=3' \
sickcodes/dock-droid:latest
```### UEFI BOOT
Add the following: `-bios /usr/share/OVMF/x64/OVMF.fd \` to Launch.sh
Or as a `docker run` argument:
UEFI Boot
```bash
docker run -it \
--device /dev/kvm \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
-e EXTRA='-bios /usr/share/OVMF/x64/OVMF.fd' \
sickcodes/dock-droid:latest
```### Custom Build
To use an alternative `CDROM`, you have two choices: runtime or buildtime.
You can add your image to the Dockerfile during the build:
```bash
CDROM_IMAGE_URL='https://sourceforge.net/projects/blissos-x86/files/Official/bleeding_edge/Generic%20builds%20-%20Pie/11.13/Bliss-v11.13--OFFICIAL-20201113-1525_x86_64_k-k4.19.122-ax86-ga-rmi_m-20.1.0-llvm90_dgc-t3_gms_intelhd.iso'
docker build \
-t dock-droid-custom \
-e CDROM_IMAGE_URL="${CDROM_IMAGE_URL}" .```
**OR** you can add it during runtime to the docker hub images as follows.
```console
-v "${CDROM}:/cdrom" \
-e CDROM=/cdrom \```
For example:```bash
# full path to your image on the host
CDROM="${HOME}/Downloads/image.iso"docker run -it \
--device /dev/kvm \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
-v "${CDROM}:/cdrom" \
-e CDROM=/cdrom \
sickcodes/dock-droid:latest
```### Force Boot CDROM QEMU
`-boot d ` will force QEMU to boot from the CDROM.
`-e EXTRA='-boot d ' \`
### Naked Container
Reduces the image size by 600Mb if you are using a local directory disk image:
```
docker cp image_name /home/arch/dock-droid/android.qcow2 .
```# Modifying the Android filesystem.
The following groups of commands is for editing `android.qcow2`.
First, we will mount the main `qcow2` file using `libguestfstools`
Then, inside that qcow2 image, there are:
`system.img`
`ramdisk.img`GRUB is also in there.
Mount the qcow2 using:
```bash
# on the host
# enable qemu-nbd for network device mounting
# wget -O android.qcow2 https://image.sick.codes/android.BlissOS_Stable.qcow2sudo modprobe nbd
sudo qemu-nbd --connect=/dev/nbd0 android.qcow2 -f qcow2
sudo fdisk /dev/nbd0 -l
mkdir -p /tmp/image
sudo mount /dev/nbd0p1 /tmp/image
```Now you can mount the internal disks in other places...
```bash
# make a folder to mount the whole resizable image
# make another to mount the raw Android image within that resizable image.
mkdir -p /tmp/system
sudo mount /tmp/image/bliss-x86-11.13/system.img /tmp/systemls /tmp/system
ls /tmp/image/bliss-x86-11.13
# don't forget to unmount
```### Swap from Houdini to `ndk_translation` Android x86
Extract the native-bridge using the following: https://github.com/sickcodes/Droid-NDK-Extractor
Thanks to [Frank from Redroid](https://github.com/zhouziyang) for the idea!
[https://github.com/remote-android/redroid-doc/tree/master/native_bridge](https://github.com/remote-android/redroid-doc/tree/master/native_bridge)
```bash
# warning, this will extract overwriting /etc/system/... so make sure you're in /tmp
cd /tmp \
&& sudo wget https://github.com/sickcodes/dock-droid/raw/master/native-bridge.tar.gz \
&& sudo tar -xzvf native-bridge.tar.gz \
&& sudo rm native-bridge.tar.gzsudo touch /tmp/system/vendor/etc/init/nativebridge.rc
sudo tee /tmp/system/vendor/etc/init/nativebridge.rc < /tmp/ramdisk.img.new
mv /tmp/ramdisk.img.new /tmp/image/bliss-x86-11.13/ramdisk.img# sudo tee -a /tmp/system/build.prop <<'EOF'
# ro.dalvik.vm.native.bridge=libndk_translation.so
# ro.product.cpu.abilist=x86_64,arm64-v8a,x86,armeabi-v7a,armeabi
# ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi
# ro.ndk_translation.version=0.2.2
# EOF# don't forget to unmount
```# Install Magisk using [https://github.com/axonasif/rusty-magisk](rusty-magisk) by [@axonasif](https://github.com/axonasif)
Inside the `ramdisk.img`, we would like to overwrite `init` with `rusty-magisk`
```bash
mkdir -p /tmp/ramdisksudo /bin/bash -c "
cd /tmp/ramdisk
zcat /tmp/image/bliss-x86-11.13/ramdisk.img | cpio -iud && mv /tmp/ramdisk/init /tmp/ramdisk/init.realwget -O /tmp/ramdisk/init https://github.com/axonasif/rusty-magisk/releases/download/v0.1.7/rusty-magisk_x86_64
chmod a+x /tmp/ramdisk/init
touch /tmp/image/bliss-x86-11.13/ramdisk.img
/bin/bash -c 'find . | cpio -o -H newc | sudo gzip > /tmp/image/bliss-x86-11.13/ramdisk.img'
"
sudo rm -rf /tmp/ramdisk
# don't forget to unmount
```During the next boot you will have Magisk installed.
### Add secure ADB keys.
```bash
# generate keys if you don't have already
KEYNAME=adbkey
adb keygen ~/.android/"${KEYNAME}"
touch ~/.android/"${KEYNAME}.pub"
adb pubkey ~/.android/"${KEYNAME}" > ~/.android/"${KEYNAME}.pub"# put some keys in the box and copy to your host ~/.android folder
mkdir -p /tmp/image/bliss-x86-11.13/data/.android
mkdir -p /tmp/image/bliss-x86-11.13/data/misc/adb
tee /tmp/image/bliss-x86-11.13/data/misc/adb/adb_keys < ~/.android/"${KEYNAME}.pub"
# don't forget to unmount
```# Unmount when finished
After completing any of the above automation, you need to unmount the disk.
```bash
# sudo mount /tmp/image/bliss-x86-11.13/ramdisk.img /tmp/ramdisk
# unmount both disks when you're done
sudo umount /tmp/ramdisk
sudo umount /tmp/system
sudo umount /tmp/image
sudo qemu-nbd -d /dev/nbd0
```# Use Frida (latest)
```bash
# choose a version from https://github.com/frida/frida/releases/
# use arm if you're debugging arm apps, via houdini or native bridge (ndk)
HOST_ARCH=x86_64
# HOST_ARCH=arm
GUEST_SYS=android
FRIDA_RELEASE=frida-serverFRIDA_RELEASES=($(curl https://github.com/frida/frida/releases | grep -Po "(?<=\ the online documentation for that is very bad and mostly outdated(due to kernel and qemu updates). But here's some references that helped me set it up several times:
>
[https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Plain_QEMU_without_libvirt](https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF#Plain_QEMU_without_libvirt)
>
[https://www.kernel.org/doc/Documentation/vfio.txt](https://www.kernel.org/doc/Documentation/vfio.txt)
>
>
> the general summary:
>
> * make sure your hardware supports VT-d/AMD-VI and UEFI and linux have it enabled
>
> * figure out which devices are in the same iommu group
>
> * detach all drivers from those devices
>
> * attach vfio-pci to those devicesAdd the following lines when you are ready:
```bash
--privileged \
-e EXTRA="-device vfio-pci,host=04:00.0' \
```## GPU Sharing
Work in progress
```bash
sudo tee -a /etc/libvirt/qemu.conf <<'EOF'
cgroup_device_acl = [
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm",
"/dev/vfio/vfio",
"/dev/dri/card0",
"/dev/dri/card1",
"/dev/dri/renderD128"
]
EOF# --device /dev/video0 \
# --device /dev/video1 \grep "video\|render" /etc/group
# render:x:989:
# video:x:986:sddmsudo usermod -aG video "${USER}"
sudo systemctl restart libvirtd
docker run -it \
-v "${PWD}/android.qcow2:/home/arch/dock-droid/android.qcow2" \
--privileged \
--device /dev/kvm \
--device /dev/video1 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e "DISPLAY=${DISPLAY:-:0.0}" \
-p 5555:5555 \
-p 50922:10022 \
--user 1000:1000 \
--group-add=966 \
--group-add=989 \
--device /dev/dri/renderD128:/dev/dri/renderD128 \
--device /dev/dri/card0:/dev/dri/card0 \
--device /dev/dri/card1:/dev/dri/card1 \
sickcodes/dock-droid:naked# pick which graphics card
# --device /dev/dri/card0:/dev/dri/card0 \```
### Convert BlissOS Virtual Box to Dock-Droid
```bash
qemu-img convert -f vdi -O qcow2 BlissOS.vdi android.qcow2
```## Building a headless container to run remotely with secure VNC
Add the following line:
`-e EXTRA="-display none -vnc 0.0.0.0:99,password=on"`
In the Docker terminal, press `enter` until you see `(qemu)`.
Type `change vnc password someusername`
Enter a password for your new vnc username^.
You also need the container IP: `docker inspect | jq -r '.[0].NetworkSettings.IPAddress'`
Or `ip n` will usually show the container IP first.
Now VNC connect using the Docker container IP, for example `172.17.0.2:5999`
Remote VNC over SSH: `ssh -N [email protected] -L 5999:172.17.0.2:5999`, where `1.1.1.1` is your remote server IP and `172.17.0.2` is your LAN container IP.
Now you can direct connect VNC to any container built with this command!
# BlissOS Image Builder Using Platform Manifests
**This requires 250GB of REAL space.**
This was previously at `./build`, but due to Docker Hub using the wrong README.md file, I have added these instructions below:
Make and add a non-root user
```bashUSERADD=user
useradd "${USERADD}" -p "${USERADD}"
tee -a /etc/sudoers <<< "${USERADD} ALL=(ALL) NOPASSWD: ALL"
mkdir -p "/home/${USERADD}"
chown "${USERADD}:${USERADD}" "/home/${USERADD}"# passwd user <