Сборка на Android проект в Docker контейнер.

При разработката на проект за платформата Android, дори и най-малкият, рано или късно трябва да се изправим пред средата за разработка. Освен Android SDK, е необходимо да имаме последната версия на Kotlin, Gradle, platform-tools, build-tools. И ако на машината на разработчика всички тези зависимости се решават предимно с помощта на Android Studio IDE, то на CI/CD сървъра всяко обновление може да се превърне в главоболие. И ако в уеб разработката решението на проблема със средата стана стандарт с Docker, то защо да не опитаме да решим аналогичен проблем и в Android разработката...

За тези, които не знаят какво е Docker - ако трябва да го обясним в най-простия вид, то това е инструмент за създаване на т.нар. „контейнери“, в които се съдържа минималното ядро на операционната система и необходимият набор от софтуер, които можем да разгръщаме където пожелаем, като същевременно запазваме средата. Какво точно ще има в нашия контейнер се определя в Dockerfile, който след това се събира в образ, който може да се стартира навсякъде и притежава свойства на идемпотентност.

Процесът на инсталиране и основите на Docker са добре описани на неговия официалния сайт. Следователно, забягвайки малко напред, ето какъв Dockerfile получихме

# Т.к. основным инструментом для сборки 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"

Запазваме го в папка с нашия Android проект и стартираме изграждането на контейнера с командата

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

Параметър -t определя таг или името на нашия контейнер, което обикновено се състои от името и версията му. В нашия случай го нарекохме android-build, а в версията посочихме комбинация от версиите на gradle, android-sdk и platform-tools. В по-нататъшните етапи ще ни бъде по-лесно да търсим нужния образ по името, използвайки такава „версия“.

След като изграждането приключи, можем да използваме нашия образ локално, можем да го качим с командата docker push в публичен или частен репозиторий на образи, за да можем да го изтеглим на други машини.

Като пример ще изградим проекта локално. За целта в папката с проекта изпълняваме командата

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

Нека разгледаме какво означава тя:

docker run — самата команда за стартиране на образа
-rm — означава, че след спиране на контейнера той изтрива всичко, което е създадено по време на живота си
-v "$PWD":/home/gradle/ — монтира текущата папка с нашия Android проект в вътрешната папка на контейнера /home/gradle/
-w /home/gradle — задава работната директория на контейнера
android-build:5.4.1-28-27 — името на нашия контейнер, който създадохме
gradle assembleDebug — самата команда за изграждане, която събира нашия проект

Ако всичко се нареди, след няколко секунди/минути ще видите на екрана си нещо подобно BUILD SUCCESSFUL за 8м 3с! А в папката app/build/output/apk ще се намира сглобеното приложение.

По подобен начин можете да изпълните и други задачи на gradle — да проверите проекта, да стартирате тестове и т.н. Основното предимство е, че при необходимост от изграждане на проекта на друга машина, не е необходимо да се притеснявате за инсталирането на цялата среда, а е достатъчно да изтеглите необходимия образ и да стартирате изграждането в него.

Контейнерът не съхранява никакви промени и всяко изграждане започва от нулата, което от една страна гарантира идентичност на изграждането независимо от местоположението, а от друга страна всеки път трябва да се изтеглят всички зависимости и да се компилира целият код отново, което понякога може да отнеме значително време. Поради това, освен обикновения "студен" старт, имаме вариант за стартиране на изграждане с запазване на т.н. "кеш", при който запазваме папката ~/ .gradle просто като я копираме в работната папка на проекта, а в началото на следващото изграждане я връщаме обратно. Всички процедури по копиране сме изнесли в отделни скриптове и самата команда за стартиране изглежда така

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"

В крайна сметка средното време за изграждане на проекта ни е намалено многократно (в зависимост от броя на зависимостите в проекта, но средният проект започна да се изгражда за 1 минута вместо 5 минути).

Всичко това има смисъл само ако разполагате със собствен вътрешен CI/CD сървър, чиято поддръжка осигурявате сами. Но в момента има много облачни услуги, в които всички тези проблеми са решени и не е нужно да се притеснявате за тях, а нужните свойства на изграждането могат да се зададат и в настройките на проекта.

Само регистрирани потребители могат да участват в анкетата. Влезте, моля.

Държите ли системата CI/CD вътре или ползвате външен сервис?

  • Използваме вътрешен сървър

  • Използваме външен сервис

  • Не използваме CI/CD

  • Друго

Гласуваха 42 потребителя. Въздържаха се 16 потребителя.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster