# syntax=docker/dockerfile:1 # # docker/android.Dockerfile # --------------------------------------------------------------------------- # Reproducible Android build environment for Wisp (Expo SDK 56 / RN 0.85). # # This image contains everything needed to run: # bunx expo prebuild --platform android --no-install # cd android && ./gradlew assembleRelease # # It is used both in CI (.gitea/workflows/ci.yml -> build-apk) and locally # (see docs/DEPLOY.md "Build the APK locally") so the APK is built identically # everywhere. The repository itself is mounted in at run time; this image only # provides the toolchain (JDK + Android SDK + Bun), not the source. # # --------------------------------------------------------------------------- # Pinned tool versions (Expo SDK 56 / React Native 0.85 era). # Sourced from node_modules/react-native/gradle/libs.versions.toml: # compileSdk = 36 targetSdk = 36 minSdk = 24 # buildTools = 36.0.0 # ndkVersion = 27.1.12297006 (installed lazily by Gradle if a module needs it) # AGP = 8.12.0 Kotlin = 2.1.20 Gradle wrapper = 9.3.1 # # IMPORTANT: pin to JDK 17. AGP 8.x targets JDK 17; the dev machine may have a # newer JDK (e.g. JDK 26), but CI/Docker MUST use 17 for reproducible, supported # builds. See docs/DEPLOY.md. # --------------------------------------------------------------------------- FROM eclipse-temurin:17-jdk # ---- Build-time version arguments (override with --build-arg if needed) ---- # Android compile/target SDK platform required by Expo SDK 56 / RN 0.85. ARG ANDROID_PLATFORM_VERSION=36 # Android build-tools version matching libs.versions.toml (buildTools = 36.0.0). ARG ANDROID_BUILD_TOOLS_VERSION=36.0.0 # Google's commandline-tools package. "latest" via the published zip; pinned to a # known build number for reproducibility. Update from: # https://developer.android.com/studio#command-line-tools-only ARG ANDROID_CMDLINE_TOOLS_VERSION=11076708 # ---- Android SDK locations (both vars set for tool compatibility) ---------- ENV ANDROID_HOME=/opt/android-sdk ENV ANDROID_SDK_ROOT=/opt/android-sdk # Put the SDK tools on PATH. cmdline-tools live under .../cmdline-tools/latest/bin # (we deliberately install them into a directory literally named "latest", which # is what sdkmanager expects). ENV PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools # Non-interactive apt for clean CI logs. ENV DEBIAN_FRONTEND=noninteractive # ---- OS packages ----------------------------------------------------------- # - unzip/curl: fetch + extract the cmdline-tools zip # - git: expo prebuild / some gradle tasks shell out to git # - bash: scripts/ci-android-sign.sh is bash (the default sh would do, but be explicit) # - ca-certificates: TLS for downloads (sdkmanager, gradle, HF, etc.) RUN apt-get update \ && apt-get install -y --no-install-recommends \ unzip \ curl \ git \ bash \ ca-certificates \ && rm -rf /var/lib/apt/lists/* # ---- Install Bun (JS package manager / task runner) ------------------------ # Wisp uses Bun, not npm/yarn. The official installer drops Bun into ~/.bun. # We run as root in this image, so HOME=/root. ENV BUN_INSTALL=/root/.bun ENV PATH=${BUN_INSTALL}/bin:${PATH} RUN curl -fsSL https://bun.sh/install | bash \ && bun --version # ---- Install the Android SDK commandline tools ----------------------------- # Download the Linux cmdline-tools zip and unpack it into the directory layout # sdkmanager requires: $ANDROID_HOME/cmdline-tools/latest/... RUN mkdir -p ${ANDROID_HOME}/cmdline-tools \ && curl -fsSL -o /tmp/cmdline-tools.zip \ "https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_CMDLINE_TOOLS_VERSION}_latest.zip" \ && unzip -q /tmp/cmdline-tools.zip -d /tmp/cmdline-tools \ # The zip extracts to a top-level "cmdline-tools" dir; move it to "latest". && mv /tmp/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest \ && rm -rf /tmp/cmdline-tools.zip /tmp/cmdline-tools # ---- Accept licenses and install SDK packages ------------------------------ # `yes |` auto-accepts every interactive license prompt. We install: # - platform-tools (adb, etc.) # - platforms;android-36 (compileSdk/targetSdk = 36) # - build-tools;36.0.0 (aapt2, zipalign, apksigner, ...) # The NDK (27.1.12297006) is intentionally NOT pre-installed: most JS-only Expo # apps don't need it, and Gradle will download the exact required NDK on demand. # If your native deps require it at build time, add: # "ndk;27.1.12297006" # to the sdkmanager line below to bake it in (saves time but enlarges the image). RUN yes | sdkmanager --licenses > /dev/null \ && sdkmanager --install \ "platform-tools" \ "platforms;android-${ANDROID_PLATFORM_VERSION}" \ "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \ && yes | sdkmanager --licenses > /dev/null # Gradle home lives outside the mounted repo so the daemon cache can persist via # a Docker volume between builds (see docs/DEPLOY.md for the local-build command). ENV GRADLE_USER_HOME=/opt/gradle # The repository is mounted here at run time (e.g. `-v "$PWD":/workspace`). WORKDIR /workspace # Default to an interactive shell; CI overrides this with an explicit build # command (`bash -lc "..."`). Documented usage is in docs/DEPLOY.md. CMD ["bash"]