FROM ubuntu:24.04 # ── Metadata ──────────────────────────────────────────────────────────────── LABEL maintainer="HuggingFace Space" LABEL description="Ubuntu 24.04 XFCE Desktop via noVNC – PRoot-Distro Style" LABEL version="1.0.0" # ── Environment ───────────────────────────────────────────────────────────── ENV DEBIAN_FRONTEND=noninteractive \ TZ=UTC \ LANG=en_US.UTF-8 \ LANGUAGE=en_US:en \ LC_ALL=en_US.UTF-8 \ DISPLAY=:1 \ VNC_PORT=5901 \ NOVNC_PORT=6080 \ DASH_PORT=5000 \ NGINX_PORT=7860 \ RESOLUTION=1280x720 \ COLOR_DEPTH=16 \ VNC_PASSWORD="" \ HOME=/data/home \ USER=ubuntu \ XDG_RUNTIME_DIR=/tmp/runtime-ubuntu # ── Stage 1: base tools + locale ──────────────────────────────────────────── # Install curl/gnupg/ca-certificates first so we can add the Mozilla apt repo. RUN apt-get update && apt-get install -y --no-install-recommends \ locales \ ca-certificates \ curl \ wget \ gnupg \ && locale-gen en_US.UTF-8 \ && update-locale LANG=en_US.UTF-8 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # ── Stage 2: Mozilla apt repo ─────────────────────────────────────────────── # firefox-esr is a Debian package; Ubuntu 24.04 ships Firefox as a snap which # does NOT work inside Docker containers. Mozilla's official deb repo is the # correct fix for Ubuntu 24.04 Docker images. RUN install -d -m 0755 /etc/apt/keyrings \ && curl -fsSL https://packages.mozilla.org/apt/repo-signing-key.gpg \ -o /etc/apt/keyrings/packages.mozilla.org.asc \ && echo "deb [signed-by=/etc/apt/keyrings/packages.mozilla.org.asc] \ https://packages.mozilla.org/apt mozilla main" \ > /etc/apt/sources.list.d/mozilla.list \ && printf 'Package: *\nPin: origin packages.mozilla.org\nPin-Priority: 1000\n' \ > /etc/apt/preferences.d/mozilla # ── Stage 3: full package install ─────────────────────────────────────────── RUN apt-get update && apt-get install -y --no-install-recommends \ # Desktop xfce4 \ xfce4-goodies \ xfce4-terminal \ xfce4-taskmanager \ # VNC (tigervnc provides Xvnc binary; more reliable on 24.04 than tightvnc) tigervnc-standalone-server \ tigervnc-tools \ # noVNC + bridge novnc \ websockify \ # X11 helpers dbus-x11 \ x11-xserver-utils \ x11-utils \ xdg-utils \ # Browser – resolved from Mozilla apt repo added in Stage 2 firefox-esr \ # Web server nginx \ # Process manager supervisor \ # Python runtime python3 \ python3-pip \ python3-venv \ # Shell tools nano \ htop \ git \ unzip \ zip \ net-tools \ procps \ sudo \ && apt-get autoremove -y \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # ── Create ubuntu user ─────────────────────────────────────────────────────── RUN useradd -m -s /bin/bash -u 1000 ubuntu \ && echo "ubuntu:ubuntu" | chpasswd \ && echo "ubuntu ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \ && mkdir -p /tmp/runtime-ubuntu \ && chown ubuntu:ubuntu /tmp/runtime-ubuntu \ && chmod 700 /tmp/runtime-ubuntu # ── Python dependencies ────────────────────────────────────────────────────── COPY requirements.txt /tmp/requirements.txt RUN pip3 install --break-system-packages --no-cache-dir -r /tmp/requirements.txt # ── Application files ──────────────────────────────────────────────────────── RUN mkdir -p /app COPY app.py /app/app.py COPY healthcheck.py /app/healthcheck.py # ── Config files ───────────────────────────────────────────────────────────── COPY supervisord.conf /etc/supervisor/conf.d/desktop.conf COPY nginx.conf /etc/nginx/sites-available/default # ── Shell scripts ──────────────────────────────────────────────────────────── COPY start.sh /start.sh COPY setup_storage.sh /setup_storage.sh COPY setup_ubuntu.sh /setup_ubuntu.sh COPY setup_vnc.sh /setup_vnc.sh RUN chmod +x /start.sh /setup_storage.sh /setup_ubuntu.sh /setup_vnc.sh # ── Remove default nginx site if it conflicts ──────────────────────────────── RUN rm -f /etc/nginx/sites-enabled/default \ && ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default # ── Expose HF Spaces port ──────────────────────────────────────────────────── EXPOSE 7860 # ── Health check ───────────────────────────────────────────────────────────── HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \ CMD python3 /app/healthcheck.py # ── Entry point ────────────────────────────────────────────────────────────── CMD ["/start.sh"]