Kompilacja projektu Android w kontenerze Docker

Pracując nad projektem na platformę Android, nawet w przypadku najmniejszego, prędzej czy później napotykamy na środowisko do programowania. Oprócz Android SDK, konieczne jest posiadanie najnowszej wersji Kotlin, Gradle, platform-tools, build-tools. A jeśli na maszynie dewelopera wszystkie te zależności są w dużej mierze zarządzane za pomocą Android Studio IDE, to na serwerze CI/CD każda aktualizacja może stać się prawdziwym wyzwaniem. Podczas gdy w web-developmencie rozwiązaniem kwestii środowiska stał się Docker, dlaczego by nie spróbować rozwiązać podobny problem w Android-developmencie...

Dla tych, którzy nie wiedzą, czym jest Docker — mówiąc najprościej, to narzędzie do tworzenia tzw. "kontenerów", które zawierają minimalne jądro systemu operacyjnego oraz niezbędny zestaw oprogramowania, które możemy wdrażać gdzie chcemy, zachowując przy tym środowisko. Co dokładnie będzie w naszym kontenerze, definiuje Dockerfile, który następnie jest budowany w obraz uruchamiany wszędzie, posiadający właściwości idempotencji.

Proces instalacji i podstawy Dockera są doskonale opisane na jego oficjalnej stronie. Dlatego, wyprzedzając nieco wydarzenia, oto jaki Dockerfile nam wyszedł

# Т.к. основным инструментом для сборки Android-проектов является Gradle, 
# и по счастливому стечению обстоятельств есть официальный Docker-образ 
# мы решили за основу взять именно его с нужной нам версией Gradle
FROM gradle:5.4.1-jdk8

# Задаем переменные с локальной папкой для Android SDK и 
# версиями платформы и инструментария
ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip" 
    ANDROID_HOME="/usr/local/android-sdk" 
    ANDROID_VERSION=28 
    ANDROID_BUILD_TOOLS_VERSION=28.0.3

# Создаем папку, скачиваем туда SDK и распаковываем архив,
# который после сборки удаляем
RUN mkdir "$ANDROID_HOME" .android 
    && cd "$ANDROID_HOME" 
    && curl -o sdk.zip $SDK_URL 
    && unzip sdk.zip 
    && rm sdk.zip 
# В следующих строчках мы создаем папку и текстовые файлы 
# с лицензиями. На оф. сайте Android написано что мы 
# можем копировать эти файлы с машин где вручную эти 
# лицензии подтвердили и что автоматически 
# их сгенерировать нельзя
    && mkdir "$ANDROID_HOME/licenses" || true 
    && echo "24333f8a63b6825ea9c5514f83c2829b004d1" > "$ANDROID_HOME/licenses/android-sdk-license" 
    && echo "84831b9409646a918e30573bab4c9c91346d8" > "$ANDROID_HOME/licenses/android-sdk-preview-license"    

# Запускаем обновление SDK и установку build-tools, platform-tools
RUN $ANDROID_HOME/tools/bin/sdkmanager --update
RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" 
    "platforms;android-${ANDROID_VERSION}" 
    "platform-tools"

Zapisujemy go w folderze z naszym projektem Android i uruchamiamy budowę kontenera poleceniem

docker build -t android-build:5.4-28-27 .

Parametr -t ustawia tag lub nazwę naszego kontenera, która zazwyczaj składa się z jego nazwy i wersji. W naszym przypadku nazwaliśmy go android-build, a w wersji wskazaliśmy zespół wersji gradle, android-sdk i platform-tools. W przyszłości łatwiej będzie nam znaleźć potrzebny obraz po nazwie, używając takiej "wersji".

Po zakończeniu budowy możemy używać naszego obrazu lokalnie, możemy go załadować poleceniem docker push do publicznego lub prywatnego repozytorium obrazów, aby pobierać go na inne maszyny.

Jako przykład zbudujemy lokalnie projekt. W tym celu w folderze z projektem wykonujemy polecenie

docker run --rm -v "$PWD":/home/gradle/ -w /home/gradle android-build:5.4.1-28-27 gradle assembleDebug

Rozłóżmy, co to oznacza:

docker run — samo polecenie uruchamiające obraz
-rm — oznacza, że po zatrzymaniu kontenera usuwa wszystko, co zostało stworzone w trakcie jego życia
-v "$PWD":/home/gradle/ — montuje bieżący folder z naszym projektem Android do wewnętrznego folderu kontenera /home/gradle/
-w /home/gradle — ustawia katalog roboczy kontenera
android-build:5.4.1-28-27 — nazwa naszego kontenera, który zbudowaliśmy
gradle assembleDebug — właściwie komenda budowy, która kompiluje nasz projekt

Jeśli wszystko pójdzie dobrze, za kilka sekund/minut zobaczycie coś na swoim ekranie, co wygląda jak BUDOWA ZAKOŃCZONA SUKCESEM w 8m 3s! A w folderze app/build/output/apk znajdziecie zbudowaną aplikację.

W podobny sposób można wykonywać inne zadania gradle — sprawdzać projekt, uruchamiać testy itd. Główną zaletą jest to, że w przypadku potrzeby zbudowania projektu na innej maszynie nie musimy się martwić o instalację całego środowiska, wystarczy pobrać odpowiedni obraz i uruchomić w nim budowę.

Kontener nie przechowuje żadnych zmian, a każda budowa zaczyna się od zera, co z jednej strony gwarantuje identyczność budowy niezależnie od miejsca jej uruchomienia, z drugiej strony za każdym razem trzeba pobierać wszystkie zależności i kompilować cały kod od nowa, co czasami może zająć znaczną ilość czasu. Dlatego oprócz zwykłego "zimnego" uruchamiania mamy opcję uruchomienia budowy z zachowaniem tzw. "cache", gdzie przechowujemy folder ~/ .gradle, po prostu kopiując go do roboczego folderu projektu, a na początku następnej budowy przywracamy go z powrotem. Wszystkie procedury kopiowania wyodrębniliśmy do oddzielnych skryptów i sama komenda uruchamiania wygląda teraz tak

docker run --rm -v "$PWD":/home/gradle/ -w /home/gradle android-build:5.4.1-28-27 /bin/bash -c ". /pre.sh; gradle assembleDebug; . /post.sh"

W rezultacie średni czas budowy projektu skrócił się kilka razy (w zależności od liczby zależności w projekcie, ale średni projekt w ten sposób zaczynał budować się w 1 minutę zamiast 5 minut).

To wszystko ma sens tylko jeśli macie własny wewnętrzny serwer CI/CD, którego obsługą sami się zajmujecie. Ale obecnie istnieje wiele usług w chmurze, w których wszystkie te problemy są rozwiązane i nie musicie się tym martwić, a potrzebne właściwości budowy można także określić w ustawieniach projektu.

Tylko zarejestrowani użytkownicy mogą brać udział w ankiecie. Zaloguj się, proszę.

Czy trzymacie system CI/CD wewnętrznie, czy korzystacie z zewnętrznej usługi

  • Używamy wewnętrznego serwera

  • Używamy zewnętrznej usługi

  • Nie używamy CI/CD

  • Inne

Głosowało 42 użytkowników. Wstrzymało się 16 użytkowników.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster