{"id":457,"date":"2025-12-17T21:35:25","date_gmt":"2025-12-18T05:35:25","guid":{"rendered":"https:\/\/junsun.net\/wordpress\/?p=457"},"modified":"2025-12-17T21:35:25","modified_gmt":"2025-12-18T05:35:25","slug":"android-cuttlefish-container-for-local-development","status":"publish","type":"post","link":"https:\/\/junsun.net\/wordpress\/2025\/12\/android-cuttlefish-container-for-local-development\/","title":{"rendered":"Android Cuttlefish Container for Local Development"},"content":{"rendered":"\n<p>Android Cuttlefish has made a lot of progress since last time I have messed with them (about 5, 6 years ago!)  For example, arm64 host is now supported.  WebRTC is finally working.  However, certain things are still pretty hideous.  Docs are scattered around.  Info are hard to find.  Simply running a CVD instance locally for dev purpose is very troublesome.<\/p>\n\n\n\n<p>So I took some time and cooked a docker container that satisfy my heart.  It basically wrap around cvd host tools and create a single CVD instance inside a container.  All the plumbing is in place to make it easy and quick to run.  I call it <a href=\"https:\/\/github.com\/monkey-jsun\/cuttlefish-host-container\/tree\/main\">cuttlefish-host-container<\/a>.<\/p>\n\n\n\n<p>Below is a straight copy of the README.md file from the github project page.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h1>cuttlefish-host-container<\/h1>\n\n\n\n<p>Docker container that runs Android cuttlefish emulators for x86_64, arm64, riscv64 guests<\/p>\n\n\n\n<h2>Background<\/h2>\n\n\n\n<p>I simply wanted to run RISC-V AOSP via cuttlefish on my laptop, and the journey wasn&#8217;t smooth.<\/p>\n\n\n\n<ul><li>The info is scarce, broken and conflicting<br><a href=\"https:\/\/github.com\/google\/android-riscv64\">https:\/\/github.com\/google\/android-riscv64<\/a><\/li><li>Host machine becomes cluttered by packages, virtual devices and run-time artifacts<\/li><li>The existing container-based solution by Google is overkill and not very user friendly<br><a href=\"https:\/\/source.android.com\/docs\/devices\/cuttlefish\/on-premises\">https:\/\/source.android.com\/docs\/devices\/cuttlefish\/on-premises<\/a><\/li><\/ul>\n\n\n\n<h2>Goal<\/h2>\n\n\n\n<p>Simple container that runs one cuttlefish instance on an x86_64 Linux host. It can run the following guests:<\/p>\n\n\n\n<ol><li>x86 guest via crosvm<\/li><li>x86 guest via qemu<\/li><li>arm64 guest via qemu<\/li><li>riscv64 guest via qemu<\/li><\/ol>\n\n\n\n<h2>Usage<\/h2>\n\n\n\n<p>Three steps to use the container:<\/p>\n\n\n\n<ol><li>Build the docker image via <code>\"docker build ...\"<\/code> (once)<\/li><li>Create or update the cvd instance via <code> \"cf-init.sh ...\"<\/code> (infrequently)<\/li><\/ol>\n\n\n\n<ul><li>populate\/update instance with aosp img zip and\/or cvd host package<\/li><\/ul>\n\n\n\n<ol><li>Run the cvd instance via <code>\"cf-run.sh\"<\/code> (frequently)<\/li><\/ol>\n\n\n\n<p>Below is a sample execution sequence:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\ndocker build . -t cf-host\n\n.\/cf-init.sh -P aosp_cf_x86_64_only_phone-img-14421689.zip -H cvd-host_package.tar.gz\n\n# run with qemu\n.\/cf-run.sh\ngvncviewer localhost\n\n# or run with crosvm, much faster\n.\/cf-run.sh -- -e CF_VM_MANAGER=crosvm -e CF_START_WEBRTC=true\nfirefox https:\/\/localhost:8443\n<\/code><\/pre>\n\n\n\n<p>You can find the product img zip file and cvd host package<a href=\"https:\/\/ci.android.com\/builds\/branches\/aosp-android-latest-release\/grid?legacy=1\"> at here<\/a>:<\/p>\n\n\n\n<p>Or build them from your own aosp tree:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nsource build\/envsetup.sh\nlunch aosp_cf_x86_64_only_phone-aosp_current-userdebug\nm dist\n# packages are in $(ANDROID_ROOT)\/out\/dist\/\n<\/code><\/pre>\n\n\n\n<p>Additional notes:<\/p>\n\n\n\n<ul><li>run <code>cf-init.sh -h<\/code> and <code>cf-run.sh -h<\/code> for more info<\/li><li>create multiple containers\/instances by creating multiple directories. Example: <code>mkdir riscv; cd riscv; ..\/cf-init.sh ...; ..\/cf-run.sh<\/code><ul><li>However, only one instance can run at a time due to port conflicts.<\/li><\/ul><\/li><li>ADB &amp; VNC ports are visible to the LAN. You can run on a headless server.<\/li><\/ul>\n\n\n\n<h2>TODO<\/h2>\n\n\n\n<ul><li>GPU acceleration does not work yet<\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<figure class=\"wp-block-image\"><img src=\"https:\/\/github.com\/user-attachments\/assets\/dff3fb6a-461b-440c-a323-85a6d6f9ad81\" alt=\"Screenshot\"\/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Android Cuttlefish has made a lot of progress since last time I have messed with them (about 5, 6 years ago!) For example, arm64 host is now supported. WebRTC is finally working. However, certain things are still pretty hideous. Docs are scattered around. Info are hard to find. Simply running a CVD instance locally for &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/junsun.net\/wordpress\/2025\/12\/android-cuttlefish-container-for-local-development\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Android Cuttlefish Container for Local Development&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":""},"categories":[3],"tags":[9,113,12],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/posts\/457"}],"collection":[{"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/comments?post=457"}],"version-history":[{"count":2,"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/posts\/457\/revisions"}],"predecessor-version":[{"id":459,"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/posts\/457\/revisions\/459"}],"wp:attachment":[{"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/media?parent=457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/categories?post=457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/junsun.net\/wordpress\/wp-json\/wp\/v2\/tags?post=457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}