[Root] Running Docker containers and Flatpak apps on Android phone with Termux

πŸ‡ΉπŸ‡Ό δΈ­ζ–‡η‰ˆ

There are various ways of running Docker containers on Android. First, Docker will not work in proot. And because Android kernel lacks the features which are required by dockers to run, even with root permission you still cannot run docker in chroot environment.

The non-rooted method of running Dockers on Android is to set up a virtual machine and install docker in it, see oofnikj - Docker on Termux in a VM. However this method is freaking slow.

In order to run Docker containers on Android without virtual machine and chroot (which means native and better performance), we must our Android phone and compile a custom kernel for it.

My Device: Sony Xperia 5 II (pdx206). LineageOS 20 (Android 13). The source code of the kernel is available on my Github repository. Docker containers running on Android phone

1. Check kernel compatibility

  1. First I rooted my Sony Xperia 5 II. Then I installed LineageOS 20.

  2. Install Termux. Then execute Moby’s script to check kernel’s compatibility o running docker.

1
2
3
4
5
pkg install wget tsu
wget https://raw.githubusercontent.com/moby/moby/master/contrib/check-config.sh
chmod +x check-config.sh
sed -i '1s_.*_#!/data/data/com.termux/files/usr/bin/bash_' check-config.sh
sudo ./check-config.sh
  1. The missing configs will be displayed. Take notes of these red missing configs (especially configs under Generally Necessary), we have to enable them during kernel compliation.

2. Compile custom Android kernel

In 2021, I had built a docker compatible kernel for Xiaomi Redmi Note 5 Pro (whyred). But at that time I built the kernel out of source tree (standalone) and it was hardly to done for other devices. Therefore, this time I decide to build the kernel with the source tree.

There is an offcial LineageOS port of pdx206.

We need a 64-bit Linux PC to compile the kernel. Ubuntu would be a good choice, however I use Arch Linux.

First follow the steps of Build for pdx206 - LineageOS wiki.

After syncing the code of LineageOS, we can build the kernel only. A boot.img will be generated after compliation.

  1. Enter the compliation environment.
1
2
source build/envsetup.sh
breakfast pdx206
  1. Go to the directory of kernel. Generate .config
1
2
3
cd ~/android/lineage/kernel/sony/sm8250/
export ARCH=arm64
make pdx206_defconfig
  1. Start menu configuration
1
make menuconfig
  1. A menu will pop up. Find the missing configs which listed in Moby’s script and enable them. Use Arrow keys to move, press Space to enable/disable configs. Don’t forget to hit Save before exit.

  2. We can search the configs. For example, to find CONFIG_IP_VS, type / and type the config name, it shall tell you where it is.

  3. According to the prompts of CONFIG_IP_VS, we know it is located at Networking Support -> Networking options -> Network packet filtering framework (Netfilter) -> IP virtual server support.

  4. Some configs such as CONFIG_CGROUP_HUGETLB are not available in Android kernel because the kernel of the device is too old.

  5. CONFIG_BINFMT_MISC should also be enabled in order to run x86 apps (or docker images) on ARM.

  6. After enabling missing configs, we have to modify the code of kernel/Makefile. (use patch command or edit the code directly)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
diff --git a/kernel/Makefile b/kernel/Makefile
index d5c1115..2dea801 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -121,7 +121,7 @@ $(obj)/configs.o: $(obj)/config_data.h
# config_data.h contains the same information as ikconfig.h but gzipped.
# Info from config_data can be extracted from /proc/config*
targets += config_data.gz
-$(obj)/config_data.gz: arch/arm64/configs/lavender_stock-defconfig FORCE
+$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
    $(call if_changed,gzip)

    filechk_ikconfiggz = (echo "static const char kernel_config_data[] __used = MAGIC_START"; cat $< | scripts/basic/bin2c; echo "MAGIC_END;")
  1. And modfiy net/netfilter/xt_qtaguid.c:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
--- orig/net/netfilter/xt_qtaguid.c     2020-05-12 12:13:14.000000000 +0300
+++ my/net/netfilter/xt_qtaguid.c       2019-09-15 23:56:45.000000000 +0300
@@ -737,7 +737,7 @@
{
        struct proc_iface_stat_fmt_info *p = m->private;
        struct iface_stat *iface_entry;
-       struct rtnl_link_stats64 dev_stats, *stats;
+       struct rtnl_link_stats64 *stats;
        struct rtnl_link_stats64 no_dev_stats = {0};
@@ -745,13 +745,8 @@
        current->pid, current->tgid, from_kuid(&init_user_ns, current_fsuid()));
        iface_entry = list_entry(v, struct iface_stat, list);
+       stats = &no_dev_stats;
-       if (iface_entry->active) {
-               stats = dev_get_stats(iface_entry->net_dev,
-                                     &dev_stats);
-       } else {
-               stats = &no_dev_stats;
-       }
        /*
         * If the meaning of the data changes, then update the fmtX
         * string.
  1. After that, replace original defconfig with new config
1
cp .config arch/arm64/configs/pdx206_defconfig
  1. Compile the kernel. The output boot.img will be located at ~/android/lineage/out/target/product/pdx206/.
1
2
make clean
mka bootimage
  1. Docker requires root permission to run, so we send boot.img to the phone. Then open Magisk and click “Install” β†’ “Patch boot.img”. Finally transfer the magisk-patched-boot.img back to PC.

  2. There is no need to reflash ROM after flashing a new kernel, but we should backup the original boot.img in the first place in the case our phone failed to boot.

  3. Power off the device. Enter fastboot mode, flash boot.img, that is it.

1
fastboot flash boot magisk-patched-boot.img

3. Running Docker containers

A message “There is an internal problem with your device” will pop up on every boot. Just ignore it.

  1. Open Termux, mount cgroups
1
sudo mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
  1. Enable binfmt_misc
1
2
3
su
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
echo 1 > /proc/sys/fs/binfmt_misc/status
  1. Execute Moby’s script again: sudo ./check-config.sh. Make sure everything turns green.

  2. Install docker and docker-compose.

1
2
pkg install root-repo
pkg install docker docker-compose
  1. Start docker daemon
1
sudo dockerd --iptables=false
  1. Swipe from left edge of the screen and open a new session. Run hello-world containers
1
sudo docker run hello-world
  1. We shall see this

  2. To run docker containers with --init arguments, install tini:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cd $TMPDIR/docker-build
wget https://github.com/krallin/tini/archive/v0.19.0.tar.gz
tar xf v0.19.0.tar.gz
cd tini-0.19.0
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PREFIX ..
make -j8
make install
ln -s $PREFIX/bin/tini-static $PREFIX/bin/docker-init

Now try to run more containers!

Note: The docker packages had been patched by Termux developers but still not fully-functional. Currently docker-compose is broken on Termux. And while running web services, you must add --net=host --dns=8.8.8.8 arguments.

You can run qus containers for eumlating and running x86 images on ARM.

Before exiting Termux, press CTRL+C to terminate docker daemon.

4. Install Flatpak applications

Flatpak package is not available in Termux’s repository, we have to create a chroot environment and install Flatpak in it. Flatpak apps installed on Android

  1. Setup Ubunut chroot environment

  2. Modfiy the starting script of chroot. Add this on the top to solve Failed to make / slave: Invalid argument error

1
2
3
4
busybox mount --bind /data/local/tmp/chrootubuntu /data/local/tmp/chrootubuntu

# You may umount it manually after exiting chroot
busybox umount /data/local/tmp/chrootubuntu
  1. Install Flatpak. Logout. Reboot the phone.
1
2
3
sudo apt install flatpak
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
exit
  1. Now we can install Flatpak applications. For instance ffmpeg, which is included in Freedesktop Platform:
1
flatpak install org.freedesktop.Platform
  1. Start dbus daemon before running a Flatpak application
1
2
mkdir /run/dbus
dbus-daemon --system
  1. Before running Flatpak applications, add --devel argument to view debug info.
1
flatpak run --devel --command=ffmpeg org.freedesktop.Platform -version

References


Thanks for your reading. You are welcome to share articles of Ivon's Blog (ivonblog.com). Please include the original URL when reprinting or citing articles, and abide by CC BY-NC-ND 4.0 license. For commercial use, please write an e-mail to me.

written by human, not by AI

If this article is helpful to you please consider supporting me.

Leave a comment

Choose the commenting system you like.

Please login to your Github account to leave a comment. You can post codes here for discussion. For images, please upload to Imgur and copy links. Your comments would be visible to everyone on Github Discussions.

This comment system is provided by Disqus, you may see some Disqus ADs on this page. You can leave a comment anonymously but you won't receive reply notifications.