File size: 7,694 Bytes
64a6136
 
 
 
7d78419
5c3ba51
64a6136
 
 
7d78419
64a6136
 
 
 
f154923
64a6136
 
 
 
 
 
 
 
 
7d78419
64a6136
 
 
 
 
 
 
 
 
5c3ba51
64a6136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5c3ba51
 
64a6136
 
 
 
 
 
 
 
5c3ba51
64a6136
 
 
5c3ba51
64a6136
 
 
f154923
64a6136
 
f154923
64a6136
 
 
 
 
 
 
 
 
 
 
8e095ab
64a6136
 
 
 
 
 
2e3b47f
64a6136
 
 
 
 
 
 
 
 
 
 
 
 
 
2e3b47f
64a6136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f154923
 
 
64a6136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f154923
64a6136
 
 
 
f154923
64a6136
 
 
 
 
5c3ba51
64a6136
5c3ba51
64a6136
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# ============================================
# 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/<title>noVNC<\/title>/<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 '<?xml version="1.0" encoding="UTF-8"?>' > ${HOME}/.config/openbox/rc.xml && \
    echo '<openbox_config xmlns="http://openbox.org/3.4/rc"><menu><file>menu.xml</file></menu></openbox_config>' >> ${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"]