Wirtualizacja i konteneryzacja w Androidzie

Poniżej dzielę się moją metodą na uruchomienie kilku linuxowych maszyn wirtualnych oraz dowolnych kontenerów Dockera wewnątrz tych maszyn – to wszystko w telefonie z systemem Android.
Oficjalnie docker dla Androida nie działa z powodu specyfiki androidowego krenela, ale można potestować Dockera w wirtualnej maszynie. Efekty pracy kontenerów można oglądać bezpośrednio w Androidzie, dzięki podwójnemu przekierowaniu portów – z kontenera do maszyny wirtualnej a następnie z maszyny wirtualnej do Androida. Rozwiązane jest oparte na programie do wirtualizacji i emulacji Limbo x86 PC Emulator, który to program z kolei jest oparty na QEMU. W Limbo (bez wsparcia KVM) bardzo responsywnie pracuje Alpine Linux, który posłuży nam jako host Dockera.

Instalacja Limbo x86 PC Emulator

W pierwszej kolejności instalujemy program Limbo x86 i w nim lekką dystrybucję Alpine Linux w wersji x86_64 (grupa VIRTUAL) – wykorzystując poniższe ustawienia maszyny wirtualnej:

Naciśnij tutaj, aby rozwinąć grafikę


Należy zwrócić szczególną uwagę na linię przekierowującą porty maszyny wirtualnej na Androida (ssh oraz poszczególnych serwerów WWW):
hostfwd=tcp::10022-:22,hostfwd=tcp::8080-:80,hostfwd=tcp::8081-:8081,hostfwd=tcp::8082-:8082

Film

Nim przejdziemy do instalacji Dockera poniżej krótki filmik przedstawiający to rozwiązanie. Prezentuję uruchomienie maszyny wirtualnej Alpine w Limbo X86, uruchamianie kontenerów Dockera, testowanie pod Androidem zkonteneryzowanych tak serwerów WWW, uruchamianie dodatkowej maszyny wirtualnej z Debianem na ARM-owej wersji Limbo, łączenie się wirtualnej maszyny w Limbo x86 z maszyną w Limbo ARM, łączenie się z serwerem SSH kontenera z zewnętrznego komputera:



Instalacja Dockera

Po dostosowaniu Alpine do swoich potrzeb dodajemy do pliku /etc/apk/repositories jedną linię poniższym poleceniem:
echo 'http://dl-cdn.alpinelinux.org/alpine/latest-stable/community' >> /etc/apk/repositories
następnie wpisujemy:
apk update
apk add docker wget
service docker start

Docker działa poprawnie jeżeli w wyniku poniższego polecenia wyświetli się wersja serwera:
docker info | grep rver

Jeżeli docker wystartuje, to możemy dodać go do uruchamiania wraz z systemem
rc-update add docker boot

Jeżeli jednak z powodu ograniczeń telefonu lub tabletu Docker się nie uruchomi jako usługa (jak w moim przypadku), to należy skorzystać z mojego obejścia tworząc poniższy plik uruchomieniowy:

service cgroups start
sleep 5
rm /var/run/docker.pid 2> /dev/null 
rm /var/run/docker.sock 2> /dev/null
containerd >> /var/log/containerd.log 2>&1 &
sleep 15
dockerd --dns 8.8.8.8 --mtu=1500 >> /var/log/docker.log 2>&1 &

Ponieważ jest to również przyspieszony kurs Dockera, to dla lepszego zobrazowania ograniczymy się do podstawowych funkcji tego narzędzia. Po wcześniejszym zabezpieczeniu polecam wyłączenie demona ssh i logowanie się przez telnet, co nieco odciąży urządzenie (telned jest zawarty w Alpine w paczce busybox-extras).

Dodajemy grupę docker i dołączamy swojego użytkownika do tej grupy:
addgroup docker -g 101
adduser nazwa_użytkownika docker

Od tej pory możemy pracować z Dockerem bez używania konta roota – w wersjach produkcyjnych Dockera zalecane jest jednak korzystanie z polecenia sudo i pominięcie tego kroku.

Instalacja kontenerów

Pobieramy najnowszy image Debiana:
docker pull debian

Jeżeli pobieranie zakończy się komunikatem: TLS handshake timeout, to do parametrów uruchamiania dockerd dodajemy jeszcze:
--registry-mirror=http://f2d6cb40.m.daocloud.io

Uruchamiamy kontener, instalujemy serwer lighttpd i opuszczamy kontener:
docker run --name=www_srv -it ubuntu bash
apt update
apt install lighttpd
exit

Zatrzymujemy kontener, zapisujemy jego image, sprawdzamy czy nowy obraz zapisał się poprawnie i usuwamy zbędny kontener:
docker stop www_srv
docker commit www_srv www_srv
docker images
docker rm www_srv

W celu uporządkowania adresów IP tworzymy oddzielną sieć dla Dockera:
docker network create --subnet=172.18.0.0/16 dockernet

Sprawdzamy sieci:
docker network ls

Tworzymy współdzielone katalogi (busyboxowa wersja mkdir jest bardzo uproszczona i nie pozwala na używanie list):
mkdir -p ~/www/srv_1 && mkdir ~/www/srv_2
W katalogach tych umieszczamy dokument index.html – ja umieściłem placeholdery lighttpd, tylko zmieniłem im tyluł, aby łatwo było identyfikować ich pochodzenie w późniejszych testach.

Do testów instalujemy lighttpd również na wirtualce.

Przypisujemy port 80 kontenerów do portów 8081 i 8082 wirtualki oraz dyskową przestrzeń współdzieloną, a następnie uruchamiamy kontenery w tle i serwery lighttpd:

docker run --net dockernet -v ~/www/srv_1:/var/www/html --ip 172.18.0.3 --name=www_srv_1 -p 8081:80 -dit www_srv bash
docker run --net dockernet -v ~/www/srv_2:/var/www/html --ip 172.18.0.4 --name=www_srv_2 -p 8082:80 -dit www_srv bash
for i in 1 2; do docker exec www_srv_${i} service lighttpd start; done

Sprawdzamy procesy w uruchomionym kontenerze:
docker top www_srv_1

W celu inspekcji lub doinstalowania dodatkowego oprogramowania, możemy wejść do uruchomionego kontenera poleceniem:
docker exec -ti www_srv_1 bash

Możemy już uruchomić przeglądarkę WWW w Androidzie i sprawdzić jak wygląda strona http://localhost na portach od 8080 do 8082.

Szybkość działania

Jeżeli urządzenie z Androidem posiada jądro skompilowane ze wsparciem dla KVM, to prędkość działania będzie zbliżona do pracy maszyny wirtualnej na średniej klasy komputerze PC (o ile wirtualny system będzie zgodny z architekturą urządzenia) – wtedy też Limbo zapewnia prawdziwą wirtualizację zasobów. Jeżeli wsparcia brak, to Limbo przejdzie w tryb emulacji, który jest dużo wolniejszy, ale przy silnym androidowym urządzeniu nadal o akceptowalnej wydajności i responsywności. Jeżeli telefon lub tablet są wiekowe (lub tzw. wersją ekonomiczną), to Limbo można wykorzystać już tylko do zabawy z Alpine Linux (bez Dockera) lub ze starszymi wersjami Debiana.

Podsumowanie

Moje urządzenie (Gemini PDA) nie zwiera wsparcia dla KVM, ale i tak w połączeniu z Alpine, Dockerem i odrobiną cierpliwości Limbo jest użytecznym oprogramowaniem. Im silniejsze urządzenie z Androidem, tym szybciej Limbo działa również w tym standardowym trybie emulacji. Program wymaga, by wszystkie obrazy były umieszczone na karcie pamięci. W trybie SDL renderowanie grafiki jest szybsze, ale aplikacja nie działa w tle. W trybie VNC renderowanie jest wolniejsze (co nie jest taki istotne w przypadku CLI), ale Limbo (i co za tym idzie – wirtualna maszyna) działa w tle nawet po wyłączeniu telefonu czy tabletu. Jeżeli nie chcemy oczekiwać na długie uruchomienie emulowanego systemu, to wirtualną maszynę można pauzować – wznowienie jej pracy zajmuje tylko kilka sekund. Docker na telefonie sprawdza się w prostych zastosowaniach programistycznych i administracyjnych. Polecam.

Więcej informacji o Limbo można znaleźć na stronie GitHub projektu oraz na nieistniejącej już oficjalnej stronie emulatora (w web.archive.org).

Dodaj komentarz

This site uses Akismet to reduce spam. Learn how your comment data is processed.