sandbox-service/Dockerfile.runner
Rama main · réplica de lectura del repositorio original.
# Aivory Python sandbox — runtime image (design.md §4.5).
#
# This is the image each session container runs. It is a pure-Python runtime
# (no Node.js) carrying the data-science stack + document-generation deps from
# §4.5, plus CJK / emoji fonts so matplotlib charts and generated PDF/PPT/DOCX
# render Chinese without tofu boxes.
#
# docker build -f Dockerfile.runner -t aivory-sandbox:latest .
#
# The container itself does nothing but `sleep infinity`; the sidecar
# (app.py) runs code inside it via `docker exec`.
FROM python:3.12-slim-bookworm
ENV DEBIAN_FRONTEND=noninteractive \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PIP_NO_CACHE_DIR=1 \
MPLBACKEND=Agg \
MPLCONFIGDIR=/home/sandbox/.config/matplotlib
# --- System deps -----------------------------------------------------------
# weasyprint (HTML->PDF) needs pango/cairo/gdk-pixbuf/harfbuzz; matplotlib &
# PDF/PPT generation need fonts. `fonts-noto-cjk` is the one that kills the
# "Chinese shows as boxes" bug (§4.5 镜像清单).
RUN apt-get update && apt-get install -y --no-install-recommends \
# weasyprint / cairo / pango runtime
libpango-1.0-0 libpangocairo-1.0-0 libcairo2 libgdk-pixbuf-2.0-0 \
libffi8 libharfbuzz0b libfribidi0 libjpeg62-turbo libopenjp2-7 \
shared-mime-info \
# fonts: CJK + emoji + western + math
fonts-noto-cjk fonts-noto-cjk-extra fonts-noto-color-emoji \
fonts-dejavu fonts-dejavu-extra fonts-noto-core \
# handy binaries
fontconfig poppler-utils coreutils \
&& rm -rf /var/lib/apt/lists/* \
&& fc-cache -f
# --- Python packages -------------------------------------------------------
# Common data-science + document-generation set (§4.5), VERSION-PINNED for
# reproducibility + supply-chain safety (see runner-requirements.txt). Kept to a
# "batteries included but not 2GB" selection; add heavyweight extras
# (playwright/chromium, LibreOffice) by uncommenting the blocks at the bottom.
COPY runner-requirements.txt /tmp/runner-requirements.txt
RUN pip install --upgrade pip \
&& pip install -r /tmp/runner-requirements.txt \
&& rm -f /tmp/runner-requirements.txt
# --- Non-root user + workspace --------------------------------------------
RUN useradd --create-home --uid 1000 sandbox \
&& mkdir -p /workspace/uploads /workspace/outputs \
/home/sandbox/.config/matplotlib \
&& chown -R sandbox:sandbox /workspace /home/sandbox
# matplotlib: default to a CJK-capable font + render minus signs correctly.
RUN printf '%s\n' \
'font.family: sans-serif' \
'font.sans-serif: Noto Sans CJK SC, Noto Sans CJK JP, WenQuanYi Zen Hei, DejaVu Sans' \
'axes.unicode_minus: False' \
'figure.dpi: 120' \
'savefig.bbox: tight' \
> /home/sandbox/.config/matplotlib/matplotlibrc \
&& chown sandbox:sandbox /home/sandbox/.config/matplotlib/matplotlibrc
USER sandbox
WORKDIR /workspace
CMD ["sleep", "infinity"]
# --- Optional heavyweight extras (uncomment if you need them) ---------------
# Playwright + headless Chromium for HTML screenshots (§4.5.1). Adds ~400MB.
# USER root
# RUN pip install playwright && playwright install --with-deps chromium
# USER sandbox
#
# LibreOffice (soffice) for format conversion / rendering pptx. Adds ~500MB.
# USER root
# RUN apt-get update && apt-get install -y --no-install-recommends libreoffice-impress libreoffice-writer libreoffice-calc \
# && rm -rf /var/lib/apt/lists/*
# USER sandbox