We detected you are likely not from a Russian-speaking region. Would you like to switch to the international version of the site?

  Назад к списку статей

Создание полностью автономного CI/CD в Termux: Docker‑контейнеры, GitLab‑раннеры и автоматическое тестирование Android‑приложений

Пошаговый план автономного CI/CD в Termux: Docker-контейнеры, развёртывание GitLab Runner и запуск автоматических тестов Android-приложений. Практические рекомендации по безопасности и надёжности.

Автономный CI/CD на базе Termux — это реалистичный способ ускорить разработку Android‑приложений, не завися от внешних CI‑провайдеров. В этой статье покажем, как собрать полностью автономную среду: Termux + Docker‑контейнеры + GitLab‑Runner, а также как организовать автоматическое тестирование Android‑приложений (unit-тесты и инструментальные тесты) в согласованном пайплайне.

Подход ориентирован на локальную разработку и внутренние стенды. Мы будем говорить о настройках, которые повышают воспроизводимость сборок и предсказуемость результатов.

Архитектура автономного CI/CD в Termux

Схема решения состоит из четырёх слоёв:

  • Termux — среда управления, запуск фоновых процессов и оркестрация.
  • Docker — изоляция окружений под разные стадии (сборка, тесты, статический анализ).
  • GitLab Runner — исполнитель job’ов, подключённый к вашему GitLab (или локальному GitLab).
  • Android build/test — инструменты Gradle/Android SDK внутри контейнеров (или в виде образов с заранее подготовленным SDK).

Ключевая идея: Runner запускает jobs, каждый job исполняется в контейнере, а зависимости (SDK/Gradle/JDK) закреплены в образах. Это минимизирует «дрейф» окружения между запусками.

Требования и подготовка окружения

Перед началом убедитесь, что у вас есть:

  • Устройство с Termux и достаточным объёмом памяти под Android SDK и кэш Gradle.
  • Доступ к Docker в Termux (Docker должен быть установлен и работоспособен в вашем окружении).
  • Рабочий GitLab (локальный или корпоративный), чтобы зарегистрировать Runner.

Рекомендуется выделить отдельные каталоги в Termux:

mkdir -p ~/ci/gitlab-runner ~/ci/docker ~/ci/android-sdk ~/ci/cache/gradle

Установка Docker и запуск Docker Engine в Termux

Точные шаги зависят от версии Termux и способа установки Docker в вашей среде, но общая логика одинаковая:

pkg update
pkg upgrade
pkg install docker

Дальше запустите Docker Engine. На практике часто используют запуск сервиса/демона или старт вручную (в зависимости от сборки и политик безопасности). После запуска проверьте доступность:

docker version
docker info

Важно: обеспечьте права и корректный доступ текущего пользователя к Docker (чтобы Runner мог запускать контейнеры).

Создание базового Docker‑образа для сборки Android

Создадим образ, который будет содержать нужный JDK, Android SDK и базовые утилиты. В промышленной практике SDK лучше «закреплять» через заранее построенный образ, чтобы jobs стартовали быстро.

Ниже пример Dockerfile. В нём показан принцип: образ готовит инструменты, а также предусматривает место под кэш Gradle. Вам потребуется адаптировать версии JDK/Android SDK под ваш проект.

# ~/ci/docker/Dockerfile.android-ci
FROM debian:stable-slim

ARG DEBIAN_FRONTEND=noninteractive

# Базовые пакеты
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl unzip ca-certificates git bash file \
    && rm -rf /var/lib/apt/lists/

# Пример установки JDK (подберите версию под ваш Gradle/AGP)
# На практике удобнее использовать официальные образы, но тут — демонстрационный шаблон.
RUN apt-get update && apt-get install -y --no-install-recommends \
    openjdk-17-jdk-headless \
    && rm -rf /var/lib/apt/lists/

ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV PATH=$JAVA_HOME/bin:$PATH

# Android SDK путь
ENV ANDROID_SDK_ROOT=/opt/android-sdk
ENV PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/tools/bin

# Подготовка SDK (подставьте корректные команды/лицензию/версии)
# Упрощённый шаблон: в реальном Dockerfile чаще используют скачивание command-line tools.
RUN mkdir -p $ANDROID_SDK_ROOT

# Убедитесь, что будет доступ к cmdline-tools и скачивание будет корректным для вашей среды.
# Для примера оставим место под установку.
# COPY cmdline-tools/ $ANDROID_SDK_ROOT/cmdline-tools/

# В продакшн-образах обычно фиксируют:
# - platform-tools
# - build-tools (несколько версий)
# - platforms;android-XX
# - cmdline-tools
# - emulator (если нужны instrumented tests)

# Создадим директорию под кэш Gradle
ENV GRADLE_USER_HOME=/cache/gradle
RUN mkdir -p /cache/gradle

WORKDIR /work

# По умолчанию команда — не требуется, Runner выполнит скрипт
CMD ["bash", "-lc", "echo Container ready"]

После сборки:

docker build -t android-ci:local -f ~/ci/docker/Dockerfile.android-ci ~/ci/docker

Если в вашем окружении нужны эмулятор/устройства для instrumented tests, добавьте в образ то, что требуется для запуска. Обычно instrumented tests требуют более сложной инфраструктуры (эмулятор, Android system image, настройки сети и т.п.). В рамках автономного сценария часто начинают с unit-тестов и затем расширяют окружение под инструментальные.

Устройство GitLab Runner для автономной работы

GitLab Runner — это агент, который принимает задания от GitLab и выполняет их. В автономном решении есть два популярных пути:

  • Runner как процесс в Termux (с использованием Docker executor).
  • Runner как контейнер (когда Termux управляет Docker хостом).

Обычно удобен первый вариант: Runner в Termux с Docker executor. Общая логика:

  1. Установить runner в Termux.
  2. Зарегистрировать его в GitLab.
  3. Настроить executor: docker.
  4. Подключить volume для кэшей (Gradle).

Установка и регистрация GitLab Runner

Для установки runner используйте доступный способ в вашем окружении (в зависимости от доступности пакетов для Termux). После установки создайте конфигурационный файл и зарегистрируйте runner через gitlab-runner register.

Примерно так выглядит последовательность (значения URL/токена — ваши):

gitlab-runner --version
gitlab-runner register

Во время регистрации вам потребуется выбрать:

  • URL GitLab: адрес вашего сервера (локальный или корпоративный).
  • Registration token: токен проекта/группы.
  • Executor: Docker.
  • Docker image (если используется напрямую): можно указывать android-ci:local или базовый образ, а затем в job — собрать всё остальное.

После регистрации проверьте конфиг: обычно он в ~/.gitlab-runner/config.toml (путь зависит от установки).

Настройка config.toml для Docker executor

Ниже упрощённый пример секции runner. Смысл: обеспечить корректный запуск контейнеров, задать кэш Gradle и рабочие директории.

# ~/.gitlab-runner/config.toml (пример фрагмента)
[[runners]]
  name = "termux-android-ci"
  url = "https://gitlab.local/"
  token = "REPLACE_ME"
  executor = "docker"

  [runners.docker]
    image = "android-ci:local"
    privileged = false
    disable_cache = false

    # Хостовые директории монтируются в контейнер для кэша
    volumes = [
      "/home/YOUR_USER/ci/cache/gradle:/cache/gradle",
      "/home/YOUR_USER/ci/gitlab-runner:/work"
    ]

  [runners.cache]
    # В Docker executor кэш часто решают volume/Gradle caching.
    # При желании можно настроить отдельное хранилище.

Подставьте ваш путь и пользователя. Идея: чтобы Gradle кэш оставался на хосте и не скачивался заново при каждом job.

Организация pipeline для Android: сборка, unit-тесты, статический анализ

Далее — ключевой файл .gitlab-ci.yml. Мы сделаем пайплайн с несколькими стадиями и чёткими артефактами.

Базовый пример для unit-тестов и сборки:

# .gitlab-ci.yml
stages:
  - prepare
  - test
  - build

variables:
  # Держим кэш Gradle внутри примонтированного volume
  GRADLE_USER_HOME: "/cache/gradle"
  # Ускорение логов, при необходимости
  GRADLE_OPTS: "-Dorg.gradle.daemon=false"

before_script:
  - java -version
  - ./gradlew --version || true

prepare:
  stage: prepare
  script:
    - chmod +x ./gradlew
    - ./gradlew tasks --all
  artifacts:
    expire_in: 1 day
    paths:
      - app/build

unit_tests:
  stage: test
  script:
    - ./gradlew testDebugUnitTest --stacktrace
  artifacts:
    when: always
    expire_in: 7 days
    reports:
      junit: "/build/test-results/test//.xml"
    paths:
      - app/build/test-results

static_analysis:
  stage: test
  script:
    # Пример: настройте под ваш инструмент (ktlint/detekt/checkstyle/lint)
    - ./gradlew lintDebug --stacktrace
  artifacts:
    when: always
    expire_in: 7 days
    paths:
      - app/build/reports

build_apk:
  stage: build
  script:
    - ./gradlew assembleDebug --stacktrace
  artifacts:
    expire_in: 14 days
    paths:
      - app/build/outputs/apk/debug/*.apk

Примечания:

  • Если у вас multi-module проект, корректируйте команды (например, module:test).
  • Если Gradle Wrapper не используется, добавьте скачивание Gradle или закрепите версию в образе.
  • Артефакты помогают быстро понять, что именно «сломалось» на этапе тестов/линта.

Автоматическое тестирование Android: unit vs instrumented

В автономной среде важно разделять типы тестов:

  • Unit-тесты (например, testDebugUnitTest) обычно не требуют устройства и могут запускаться сразу в контейнере.
  • Instrumented tests (например, через AndroidJUnitRunner на эмуляторе) требуют эмулятора или физического устройства и обычно дополнительных компонентов (system image, запуск эмулятора, виртуальные устройства/ускорение).

Для начала рекомендовано выстроить надёжный контур unit-тестов, а затем отдельно добавлять стадию для instrumented tests после того, как эмуляторная часть будет стабильна в вашем окружении.

Добавление инструментальных тестов (эскиз)

Ниже — общий шаблон стадию instrumented_tests. В реальности нужно адаптировать запуск эмулятора под ваше устройство/образ, а также обеспечить таймауты и ожидание готовности.

instrumented_tests:
  stage: test
  script:
    # Примеры шагов (адаптируйте под ваш SDK/версии):
    # 1) Создать AVD
    # 2) Запустить emulator в фоне
    # 3) Дождаться boot completion
    # 4) Выполнить connectedAndroidTest / managed device tests
    - echo "TODO: implement emulator start and waits"
    - ./gradlew connectedDebugAndroidTest --stacktrace
  artifacts:
    when: always
    expire_in: 7 days
    paths:
      - app/build/outputs/androidTest-results

Практический совет: если эмулятор нестабилен, лучше держать instrumented tests в отдельной ветке/триггере (например, по расписанию или вручную), чтобы не блокировать разработку на unit-тестах.

Кэширование и ускорение: Gradle, зависимости, SDK

Автономный CI/CD в Termux выигрывает за счёт кэширования:

  • Кэш Gradle: монтируйте /cache/gradle из хоста в контейнер.
  • Вместо установки SDK на каждом job — фиксируйте SDK в Docker‑образе.
  • Вынесите «тяжёлые» шаги в подготовительные стадии, чтобы уменьшить время первого запуска.

Проверяйте, что кэш реально используется: Gradle при корректной настройке GRADLE_USER_HOME начнёт переиспользовать зависимости.

Надёжность пайплайна: повторяемость и диагностика

Чтобы CI/CD работал предсказуемо:

  • Фиксируйте версии: JDK, Android Gradle Plugin, Build Tools и платформы Android.
  • Используйте --stacktrace и включайте корректные отчёты тестов.
  • Делайте артефакты: отчёты JUnit, логи сборки, отчёты линтера.
  • Добавляйте отдельные jobs для диагностики (например, gradlew test --tests ... при необходимости).

Безопасность и корректная эксплуатация

Даже локальный CI/CD требует дисциплины:

  • Не храните секреты прямо в .gitlab-ci.yml. Используйте переменные GitLab.
  • Ограничивайте доступ Runner’а: минимальные права на томах и файловой системе.
  • Избегайте запуска контейнеров в привилегированном режиме без необходимости.
  • Следите за обновлениями образов и зависимостей.

Если вы подключаете локальную сеть для обмена данными между устройствами (например, чтобы Runner мог обращаться к GitLab/репозиторию по локальному адресу), можно использовать VPN только для организации локальной сети — без целей обхода блокировок.

Пример: полный локальный цикл разработки

Рекомендуемый рабочий процесс может выглядеть так:

  • Разработчик пушит изменения в GitLab.
  • GitLab вызывает ваш автономный Runner.
  • Runner запускает контейнер android-ci:local.
  • Внутри контейнера выполняются: unit tests, lint, сборка APK.
  • Результаты тестов и отчёты сохраняются как артефакты.

Это даёт быстую обратную связь и снижает вероятность сюрпризов в более «тяжёлых» средах.

Заключение

Мы рассмотрели, как построить полностью автономный CI/CD в Termux: поднять Docker‑контейнеры, подключить GitLab Runner с Docker executor и организовать автоматическое тестирование Android‑приложений в пайплайне. Такой подход помогает ускорить разработку, улучшить воспроизводимость сборок и сделать контроль качества частью ежедневной рутины.

Если хотите, чтобы мы помогли вам собрать решение под ваш проект (версии Android/Gradle, структура модулей, unit vs instrumented, настройка кэшей и оптимизация времени сборки), обратитесь в РыбинскЛАБ — мы ведём внедрение и сопровождение DevOps‑практик для Android и локальных CI/CD.

* Текст статьи подготовлен и структурирован с использованием технологий искусственного интеллекта. Проверен и доработан перед публикацией.

Нужна помощь с настройкой Termux, Linux и серверов?

Я оказываю ИТ-услуги: настройка серверов, автоматизация, безопасность, помощь с Linux и инфраструктурой. Материалы сайта — только в ознакомительных и образовательных целях.

Связаться со мной
Поддержать проект