# ============================================
# Hugging Face Space: Android Studio Web
# Full IDE in browser via noVNC
# ============================================
FROM ubuntu:22.04
# --------------------------------------------
# Environment Variables
# --------------------------------------------
ENV DEBIAN_FRONTEND=noninteractive
ENV USER=user
ENV HOME=/home/user
# Android / Flutter paths
ENV ANDROID_SDK_ROOT=/opt/android-sdk
ENV ANDROID_HOME=/opt/android-sdk
ENV ANDROID_STUDIO=/opt/android-studio
ENV PUB_CACHE=/home/user/.pub-cache
# Java 21 required for Android Studio 2025+
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
# Merged PATH
ENV PATH="${ANDROID_STUDIO}/bin:${JAVA_HOME}/bin:/opt/flutter/bin:/opt/flutter/bin/cache/dart-sdk/bin:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin:${ANDROID_SDK_ROOT}/platform-tools:${ANDROID_SDK_ROOT}/emulator:${PATH}"
# Display / VNC settings
ENV DISPLAY=:1
ENV VNC_PORT=5901
ENV NOVNC_PORT=7860
ENV VNC_PASSWORD=android
# --------------------------------------------
# 1. Install System Dependencies
# --------------------------------------------
RUN apt-get update && apt-get install -y \
# Core
curl wget git unzip xz-utils zip tar \
# Java 21
openjdk-21-jdk \
# VNC + Desktop
tigervnc-standalone-server \
openbox obconf menu \
# noVNC dependencies
python3 python3-websockify net-tools \
# Android Studio GUI libs
libglu1-mesa libxkbcommon-x11-0 libxcb-xinerama0 \
libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
libxcb-randr0 libxcb-render-util0 libxcb-shape0 \
libxcb-xfixes0 libxcb-xkb1 libxcb-sync1 \
libxcb-util1 libxcb-xinput0 libfontconfig1 \
libdbus-1-3 libnss3 libxcomposite1 libxcursor1 \
libxi6 libxtst6 libxrandr2 libasound2 \
libatk-bridge2.0-0 libgtk-3-0 libgbm1 \
libegl1 mesa-utils xterm xfce4-terminal \
# Build tools
build-essential cmake ninja-build pkg-config \
libgtk-3-dev liblzma-dev libstdc++6 \
# Misc
sudo ca-certificates gnupg lsb-release \
&& rm -rf /var/lib/apt/lists/*
# --------------------------------------------
# 2. Install noVNC (Web-based VNC client)
# --------------------------------------------
RUN mkdir -p /opt/novnc/utils/websockify && \
curl -fsSL https://github.com/novnc/noVNC/archive/refs/tags/v1.4.0.tar.gz | \
tar -xz --strip-components=1 -C /opt/novnc && \
curl -fsSL https://github.com/novnc/websockify/archive/refs/tags/v0.11.0.tar.gz | \
tar -xz --strip-components=1 -C /opt/novnc/utils/websockify
# Create noVNC landing page
RUN cp /opt/novnc/vnc.html /opt/novnc/index.html && \
sed -i 's/
noVNC<\/title>/Android Studio Web<\/title>/' /opt/novnc/index.html
# --------------------------------------------
# 3. Install Android SDK Command Line Tools
# --------------------------------------------
RUN mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools && \
wget -q "https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip" -O /tmp/cmdline-tools.zip && \
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 -f /tmp/cmdline-tools.zip
# --------------------------------------------
# 4. Install Android Studio (Latest: 2025.3.4)
# --------------------------------------------
RUN wget -q --show-progress \
"https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.3.4.0/android-studio-2025.3.4.0-linux.tar.gz" \
-O /tmp/android-studio.tar.gz && \
tar -xzf /tmp/android-studio.tar.gz -C /opt && \
rm -f /tmp/android-studio.tar.gz && \
ln -sf /opt/android-studio/bin/studio.sh /usr/local/bin/android-studio
# --------------------------------------------
# 5. Install Flutter SDK (stable)
# --------------------------------------------
RUN git clone --depth 1 --branch stable https://github.com/flutter/flutter.git /opt/flutter && \
flutter config --no-analytics && \
flutter doctor --android-licenses || true
# --------------------------------------------
# 6. Accept SDK Licenses & Install Components
# --------------------------------------------
RUN yes | sdkmanager --licenses >/dev/null 2>&1 || true && \
sdkmanager \
"platform-tools" \
"platforms;android-34" \
"platforms;android-33" \
"build-tools;34.0.0" \
"build-tools;33.0.2" \
"cmdline-tools;latest" \
"extras;android;m2repository" \
"extras;google;m2repository" \
|| true
# --------------------------------------------
# 7. Create User & Set Permissions
# --------------------------------------------
RUN useradd -m -u 1000 -s /bin/bash ${USER} && \
echo "${USER} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \
mkdir -p \
${HOME}/.vnc \
${HOME}/.config/openbox \
${HOME}/.android \
${HOME}/Android/Sdk \
${HOME}/Projects && \
# VNC password
echo "${VNC_PASSWORD}" | vncpasswd -f > ${HOME}/.vnc/passwd && \
chmod 600 ${HOME}/.vnc/passwd && \
# Openbox config (minimal desktop)
echo '' > ${HOME}/.config/openbox/rc.xml && \
echo '' >> ${HOME}/.config/openbox/rc.xml && \
# Ownership
chown -R ${USER}:${USER} ${HOME} && \
chown -R ${USER}:${USER} /opt/android-studio && \
chown -R ${USER}:${USER} /opt/flutter && \
chown -R ${USER}:${USER} ${ANDROID_SDK_ROOT} && \
chown -R ${USER}:${USER} /opt/novnc
# --------------------------------------------
# 8. Configure Flutter & Cache
# --------------------------------------------
USER ${USER}
WORKDIR ${HOME}
RUN flutter config --android-sdk ${ANDROID_SDK_ROOT} && \
flutter precache && \
flutter doctor || true
# Pre-download Gradle wrapper (speeds up first build)
RUN mkdir -p ${HOME}/.gradle && \
echo "org.gradle.daemon=true" >> ${HOME}/.gradle/gradle.properties && \
echo "org.gradle.parallel=true" >> ${HOME}/.gradle/gradle.properties
# --------------------------------------------
# 9. Create Startup Script
# --------------------------------------------
USER root
RUN cat > /usr/local/bin/start-space.sh << 'EOF'
#!/bin/bash
set -e
echo "=========================================="
echo " Android Studio Web - Hugging Face Space"
echo "=========================================="
# Clean up old VNC locks (in case of restart)
rm -f /tmp/.X1-lock /tmp/.X11-unix/X1
# Start VNC server
echo "[1/4] Starting TigerVNC server on :1..."
vncserver :1 \
-geometry 1920x1080 \
-depth 24 \
-localhost no \
--I_KNOW_EXACTLY_WHAT_I_AM_DOING \
> /dev/null 2>&1
# Start Openbox window manager
echo "[2/4] Starting Openbox desktop..."
su - ${USER} -c "DISPLAY=:1 openbox &"
# Start noVNC web server (port 7860 for Hugging Face)
echo "[3/4] Starting noVNC on port ${NOVNC_PORT}..."
/opt/novnc/utils/websockify/run \
--web=/opt/novnc \
--cert=none \
--ssl-only=no \
0.0.0.0:${NOVNC_PORT} \
localhost:${VNC_PORT} &
# Auto-start Android Studio after brief delay
echo "[4/4] Launching Android Studio..."
(
sleep 4
su - ${USER} -c "DISPLAY=:1 android-studio > /home/user/.android-studio.log 2>&1 &"
) &
echo ""
echo "✅ Android Studio Web is ready!"
echo " Open your Hugging Face Space URL to access it"
echo ""
# Keep container alive
tail -f /dev/null
EOF
RUN chmod +x /usr/local/bin/start-space.sh
# --------------------------------------------
# 10. Final Config
# --------------------------------------------
USER ${USER}
WORKDIR ${HOME}
EXPOSE 7860 5901 5554 5555
CMD ["/usr/local/bin/start-space.sh"]