File size: 7,406 Bytes
b60b695 a859d16 b60b695 982e93a b60b695 982e93a b60b695 982e93a b60b695 982e93a 3cbfe5b b60b695 3cbfe5b b60b695 3cbfe5b b60b695 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | # Riaslink Port Builder โ Hugging Face Space
#
# Builds a debug or release APK from a RPG Maker MV/MZ `www/` export, with the
# RIA_TavernMenu + RIA_FPSCounter plugins (see /android-template/app/src/main/
# assets/www/js/plugins/) auto-injected into the game's own plugin list.
#
# Base image choice: eclipse-temurin's JDK image (not a generic openjdk image,
# which Docker Hub deprecated) gives a known-good JDK 17 without extra apt
# juggling; everything Android-specific (cmdline-tools, licenses, platform)
# is installed explicitly below so the exact SDK contents are visible here
# rather than hidden in a third-party Android base image.
FROM eclipse-temurin:17-jdk-jammy
ENV DEBIAN_FRONTEND=noninteractive
# UTF-8 locale for every JVM in the image (Gradle included): with an ASCII
# locale Java cannot open files whose names contain Japanese or Turkish
# characters, so those game assets silently went missing from the APK.
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
# --- System packages ---------------------------------------------------
# python3-venv: Spaces' base images vary in whether pip is pre-wired for
# the system python, a venv sidesteps that entirely.
# unzip: the Android cmdline-tools ship as a zip; also used by the pipeline
# to unpack the user's uploaded www.zip.
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 \
python3-pip \
python3-venv \
unzip \
curl \
git \
&& rm -rf /var/lib/apt/lists/*
# --- Bootstrap Gradle itself --------------------------------------------
# The template ships gradlew + gradlew.bat (the standard, version-independent
# wrapper scripts) but deliberately NOT gradle/wrapper/gradle-wrapper.jar,
# since that's a compiled binary this environment cannot author by hand.
# A real, versioned Gradle install here regenerates that jar via
# `gradle wrapper` right below, which is the officially supported way to
# produce it โ after which every actual build in this image runs through
# ./gradlew as normal, matching what a contributor's machine would do.
ARG GRADLE_VERSION=8.10.2
RUN curl -fsSL -o /tmp/gradle.zip "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" && \
unzip -q /tmp/gradle.zip -d /opt && \
ln -s /opt/gradle-${GRADLE_VERSION}/bin/gradle /usr/local/bin/gradle && \
rm /tmp/gradle.zip
# --- Android SDK ---------------------------------------------------------
# Only the pieces actually needed to run `gradlew assembleDebug/Release`
# against the template's compileSdk=35/minSdk=26 (see android-template/app/
# build.gradle.kts) are installed โ no emulator, no system images, no NDK.
ENV ANDROID_SDK_ROOT=/opt/android-sdk
ENV ANDROID_HOME=$ANDROID_SDK_ROOT
ENV PATH=$PATH:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_SDK_ROOT/platform-tools
# Version pin: commandlinetools revision current at the time this Space was
# built. If Google retires this exact URL, replace it with the current
# "Command line tools only" link from https://developer.android.com/studio
# โ the rest of this Dockerfile does not need to change.
ARG CMDLINE_TOOLS_URL=https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
RUN mkdir -p $ANDROID_SDK_ROOT/cmdline-tools && \
curl -fsSL -o /tmp/cmdline-tools.zip "$CMDLINE_TOOLS_URL" && \
unzip -q /tmp/cmdline-tools.zip -d $ANDROID_SDK_ROOT/cmdline-tools && \
mv $ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools $ANDROID_SDK_ROOT/cmdline-tools/latest && \
rm /tmp/cmdline-tools.zip
# Accepting licenses non-interactively is required before sdkmanager will
# install anything in a headless container.
RUN yes | sdkmanager --licenses > /dev/null || true
RUN sdkmanager \
"platform-tools" \
"platforms;android-35" \
"build-tools;35.0.0" \
> /dev/null
# --- Gradle cache warm-up --------------------------------------------------
# Copies just the wrapper + build files first (not the whole template) so
# Docker's layer cache can skip re-downloading Gradle/dependencies on
# rebuilds that only change app source, www content, or app.py.
WORKDIR /android-template
COPY android-template/gradle ./gradle
COPY android-template/gradlew ./gradlew
COPY android-template/gradlew.bat ./gradlew.bat
COPY android-template/settings.gradle.kts ./settings.gradle.kts
COPY android-template/build.gradle.kts ./build.gradle.kts
COPY android-template/gradle.properties ./gradle.properties
COPY android-template/app/build.gradle.kts ./app/build.gradle.kts
RUN chmod +x ./gradlew
# `help` alone is enough to make Gradle resolve the app module's dependency
# graph against real build files, without needing actual app sources yet.
# Uses the system `gradle` binary directly here (not yet ./gradlew โ see
# below for why) purely to warm Gradle's own dependency-download cache.
RUN mkdir -p app/src/main/java app/src/main/res app/src/main/assets/www && \
gradle help --no-daemon || true
# Now bring in the rest of the template (Kotlin sources, manifest, res,
# default www/ harness) that COULD NOT be copied above without invalidating
# the dependency-resolution cache layer on every source edit.
#
# IMPORTANT ORDERING NOTE: this COPY brings in the template's own
# gradle/wrapper/ folder too โ which in source control only has
# gradle-wrapper.properties, never gradle-wrapper.jar (a compiled binary
# this environment cannot author by hand; see the git history/README for
# that constraint). COPYing a directory replaces the destination's
# contents wholesale, so doing this COPY before generating the wrapper jar
# would silently overwrite it with the source tree's jar-less version โ
# that was the actual bug behind "Could not find or load main class
# org.gradle.wrapper.GradleWrapperMain" in production. Generating the
# wrapper jar (below) must run AFTER this COPY, as the last mutation to
# gradle/wrapper/ in this image, so nothing overwrites it afterward.
COPY android-template ./
# Regenerates gradle/wrapper/gradle-wrapper.jar and pins it to the same
# version as the system Gradle used to generate it, so every subsequent
# ./gradlew call in this image (including the actual per-request builds in
# build_pipeline.py) is self-contained and reproducible. Must be the LAST
# thing that touches gradle/wrapper/ in this image โ see the comment on
# the COPY above.
RUN gradle wrapper --gradle-version=${GRADLE_VERSION} --distribution-type=bin
# --- Python / FastAPI -------------------------------------------------------
WORKDIR /app
COPY requirements.txt .
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --no-cache-dir -r requirements.txt
# Fails the build here, at build time, rather than letting the container
# start, get marked healthy by Spaces, and only then crash on the first
# real request โ the same reasoning that caught the earlier Gradio
# `requests` omission before it reached production.
RUN python3 -c "import fastapi, uvicorn, multipart; print('fastapi import OK:', fastapi.__version__)"
COPY app.py build_pipeline.py ./
COPY static ./static
# Spaces expects the app to listen on 7860 by default.
EXPOSE 7860
# Builds happen in a fresh copy of /android-template per request (see
# build_pipeline.py) so concurrent builds never share mutable state;
# ANDROID_TEMPLATE_DIR tells the pipeline where that read-only source lives.
ENV ANDROID_TEMPLATE_DIR=/android-template
CMD ["python3", "app.py"]
|