parametric-2d-chess / Dockerfile
Yehor's picture
Deploy d88e23ad25d7d60048bc840a3c9f8389d5f651f6 from egorsmkv/parametric-2d-chess
cf8e8fc verified
Raw
History Blame Contribute Delete
5.82 kB
# The Space image: the Gradio app plus a headless Bambu Studio, so the
# "Slice with Bambu Studio" box actually produces a printer-ready .gcode.3mf
# instead of falling back to an unsliced plate.
#
# Build context is the assembled Space payload (app.py, chess2d/,
# requirements.txt) -- see scripts/deploy_space.py. To build it locally:
#
# python scripts/deploy_space.py --space-id local/build --dry-run
# docker build -t chess2d build/space
# docker run --rm -p 7860:7860 chess2d
#
# Ubuntu 24.04 on purpose: Bambu Studio publishes its Linux build as an
# ubuntu-24.04 AppImage, and an older base (python:*-slim is Debian 12) has too
# old a glibc to run it.
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
# Two dependency sets in one layer: Python for the app, and the GTK/GL/media
# libraries the AppImage links against. xvfb is not optional -- Bambu Studio is
# a GUI program whose command line still wants a display to start on.
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
python3 \
python3-venv \
xvfb \
libgtk-3-0 \
libwebkit2gtk-4.1-0 \
libsoup-3.0-0 \
libgl1 \
libglu1-mesa \
libegl1 \
libgstreamer1.0-0 \
libgstreamer-plugins-base1.0-0 \
libsecret-1-0 \
libnotify4 \
libdbus-1-3 \
libcurl4 \
libssl3 \
libx11-6 \
libxrandr2 \
libxinerama1 \
libxcursor1 \
libxi6 \
libfontconfig1 \
libfreetype6 \
&& rm -rf /var/lib/apt/lists/*
# Bambu Studio, extracted rather than mounted: --appimage-extract unpacks
# without FUSE, which containers do not have.
#
# Left empty, the release feed is queried for the newest Ubuntu AppImage. That
# query is an unauthenticated GitHub API call (60/hour per IP) and it makes the
# image non-reproducible, so pin an asset for anything you care about:
#
# docker build --build-arg BAMBU_STUDIO_URL=https://.../Bambu_Studio_ubuntu-24.04_vX.AppImage .
#
# The last step records where the release put its profile tree -- it has moved
# between versions -- so $BAMBU_PROFILES below is a fact, not a guess.
ARG BAMBU_STUDIO_URL=""
RUN set -eux; \
url="${BAMBU_STUDIO_URL}"; \
if [ -z "$url" ]; then \
url="$(curl -fsSL https://api.github.com/repos/bambulab/BambuStudio/releases/latest \
| grep -o 'https://[^\"]*ubuntu[^\"]*\.AppImage' | head -n 1)"; \
fi; \
test -n "$url" || { echo "could not resolve a Bambu Studio AppImage URL"; exit 1; }; \
echo "Installing Bambu Studio from $url"; \
curl -fL --retry 3 -o /tmp/BambuStudio.AppImage "$url"; \
chmod +x /tmp/BambuStudio.AppImage; \
cd /opt && /tmp/BambuStudio.AppImage --appimage-extract >/dev/null; \
mv /opt/squashfs-root /opt/bambustudio; \
rm /tmp/BambuStudio.AppImage; \
profiles="$(find /opt/bambustudio -type d -name profiles -print -quit)"; \
test -n "$profiles" || { echo "no profiles/ directory in the AppImage"; exit 1; }; \
ln -sfn "$profiles" /opt/bambustudio-profiles; \
echo "profiles: $profiles"
# A wrapper so the app finds one stable path: it supplies the virtual display
# the GUI binary insists on, and -a picks a free server number per call.
RUN printf '%s\n' \
'#!/bin/sh' \
'exec xvfb-run -a --server-args="-screen 0 1280x1024x24" /opt/bambustudio/AppRun "$@"' \
> /usr/local/bin/bambu-studio \
&& chmod +x /usr/local/bin/bambu-studio
# chess2d's own discovery hooks (see src/chess2d/bambu.py): without these it
# would search $PATH and the usual install locations and find nothing usable.
ENV BAMBU_STUDIO=/usr/local/bin/bambu-studio \
BAMBU_PROFILES=/opt/bambustudio-profiles
# A smoke test with the build log as its output: if the AppImage cannot start at
# all (a missing library, the wrong glibc) this prints the failure where a human
# will see it. The exit code is not trusted -- Bambu Studio's CLI has returned
# non-zero for --help across releases -- so it does not gate the build; the
# `image` CI job slices a real plate for that.
RUN set -eux; \
test -x /opt/bambustudio/AppRun; \
bambu-studio --help > /tmp/bambu-help.txt 2>&1 || true; \
head -n 20 /tmp/bambu-help.txt; \
rm -f /tmp/bambu-help.txt
# Hugging Face Spaces run the container as UID 1000; matching it here keeps the
# app's temp files and Bambu Studio's config directory writable. Ubuntu 24.04
# ships its own UID 1000 (`ubuntu`), which has to go first or useradd fails.
RUN userdel -r ubuntu 2>/dev/null || true; \
useradd -m -u 1000 user
# LANG matters: a bare container locale is POSIX, which makes Python's default
# text encoding ASCII, and the app reads UTF-8 SVGs. PYTHONUTF8 covers anything
# that reaches for the locale anyway.
ENV HOME=/home/user \
PATH=/opt/venv/bin:/usr/local/bin:/usr/bin:/bin \
PYTHONUNBUFFERED=1 \
PYTHONUTF8=1 \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
GRADIO_SERVER_NAME=0.0.0.0 \
GRADIO_SERVER_PORT=7860
# Ubuntu's Python is externally managed, so the app gets its own venv.
RUN python3 -m venv /opt/venv && chown -R user:user /opt/venv
USER user
WORKDIR /home/user/app
COPY --chown=user requirements.txt ./
RUN pip install --no-cache-dir --upgrade pip && pip install --no-cache-dir -r requirements.txt
COPY --chown=user . .
EXPOSE 7860
# Liveness only. A missing slicer deliberately does *not* fail this: the app
# still serves generic 3MFs, and restarting the container would not conjure
# Bambu Studio back. The build log and the `image` CI job cover that instead.
HEALTHCHECK --interval=60s --timeout=15s --start-period=60s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:7860/', timeout=10)"
CMD ["python", "app.py"]