Compilación de un proyecto de Android en un contenedor Docker.

Al desarrollar un proyecto para la plataforma Android, incluso el más pequeño, tarde o temprano hay que enfrentarse al entorno de desarrollo. Además del Android SDK, es necesario tener la última versión de Kotlin, Gradle, platform-tools y build-tools. Y mientras que en la máquina del desarrollador estas dependencias se resuelven en su mayoría mediante Android Studio IDE, en el servidor CI/CD cada actualización puede convertirse en un dolor de cabeza. Si en el desarrollo web la solución al problema del entorno se ha convertido en el estándar Docker, ¿por qué no intentar resolver un problema similar en el desarrollo de Android…?

Para aquellos que no saben qué es Docker —en términos simples, es una herramienta para crear lo que se llaman "contenedores" que contienen un núcleo mínimo del sistema operativo y el conjunto necesario de software, que podemos desplegar donde queramos, manteniendo así el entorno. Lo que habrá en nuestro contenedor se determina en el Dockerfile, que luego se compila en una imagen que se puede ejecutar en cualquier lugar y que posee propiedades de idempotencia.

El proceso de instalación y los fundamentos de Docker están perfectamente descritos en su el sitio web oficial. Por lo tanto, adelantándome un poco, este es el Dockerfile que obtuvimos

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

Lo guardamos en la carpeta de nuestro proyecto de Android y iniciamos la construcción del contenedor con el comando

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

Parámetro -t asigna una etiqueta o nombre a nuestro contenedor, que generalmente está compuesto por su nombre y versión. En nuestro caso lo llamamos android-build y en la versión indicamos la combinación de versiones de gradle, android-sdk y platform-tools. A partir de ahora será más fácil buscar la imagen que necesitamos por nombre utilizando esa "versión".

Después de que se complete la construcción, podemos usar nuestra imagen localmente, podemos cargarla con el comando docker push en un repositorio público o privado de imágenes para poder descargarla en otras máquinas.

Como ejemplo, vamos a construir el proyecto localmente. Para ello, en la carpeta del proyecto ejecutaremos el comando

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

Desglosamos lo que significa:

docker run — el comando para ejecutar la imagen
-rm — significa que después de detener el contenedor elimina todo lo que se creó durante su vida
-v "$PWD":/home/gradle/ — monta la carpeta actual con nuestro proyecto de Android en la carpeta interna del contenedor /home/gradle/
-w /home/gradle — establece el directorio de trabajo del contenedor
android-build:5.4.1-28-27 — el nombre de nuestro contenedor, que hemos construido
gradle assembleDebug — en realidad, el comando de compilación que reúne nuestro proyecto

Si todo sale bien, en unos segundos/minutos verás en tu pantalla algo como COMPILACIÓN EXITOSA en 8m 3s! Y en la carpeta app/build/output/apk estará la aplicación compilada.

De manera similar, se pueden realizar otras tareas de gradle: verificar el proyecto, ejecutar pruebas, etc. La principal ventaja es que, si necesitamos compilar el proyecto en otra máquina, no tenemos que preocuparnos por instalar todo el entorno, sino que basta con descargar la imagen necesaria y ejecutarla para la compilación.

El contenedor no almacena ningún cambio, y cada compilación se inicia desde cero, lo que, por un lado, garantiza la identidad de la compilación independientemente de dónde se ejecute, pero, por otro lado, cada vez hay que descargar todas las dependencias y compilar todo el código nuevamente, lo que a veces puede llevar un tiempo considerable. Por lo tanto, además del 'inicio en frío' normal, tenemos una opción para iniciar la compilación conservando el llamado 'caché', donde guardamos la carpeta ~/.gradle simplemente copiándola a la carpeta de trabajo del proyecto, y al comienzo de la siguiente compilación la devolvemos. Hemos trasladado todos los procedimientos de copia a scripts separados y el comando de inicio ahora se ve así

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"

Como resultado, el tiempo promedio de compilación de nuestro proyecto se redujo varias veces (dependiendo del número de dependencias en el proyecto, pero un proyecto promedio ahora se compila en 1 minuto en lugar de 5 minutos).

Todo esto, por supuesto, solo tiene sentido si tienes tu propio servidor CI/CD interno, el cual gestionas tú mismo. Pero ahora hay muchos servicios en la nube donde se han resuelto todos estos problemas y no tienes que preocuparte por ello, y las propiedades necesarias de la compilación también se pueden indicar en la configuración del proyecto.

Solo los usuarios registrados pueden participar en la encuesta. Inicie sesión, por favor.

¿Mantienes el sistema CI/CD internamente o utilizas un servicio externo?

  • Usamos un servidor interno

  • Usamos un servicio externo

  • No usamos CI/CD

  • Otro

Votaron 42 usuarios. Se abstuvieron 16 usuarios.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster