docker/sandbox/Dockerfile
Rama main · réplica de lectura del repositorio original.
# -------------------------
# MULTI-STAGE DOCKERFILE (SANDBOX)
# -------------------------
# === Stage 0: base_workers layer (common bootstrap) ============================================
FROM python:3.11-slim AS base
WORKDIR /install
RUN pip install --upgrade pip setuptools wheel
# === Stage 1: install UNHASHED packages ===============================================
FROM base AS unhashed_builder
COPY sandbox_reqs_unhashed.txt .
# Add OpenCV headless so cv2 won't look for libGL.so.1
RUN echo "opencv-python-headless" >> sandbox_reqs_unhashed.txt
RUN pip install \
--prefix=/install/packages \
--default-timeout=1800 \
--retries 30 \
-r sandbox_reqs_unhashed.txt
# === Stage 2: install HASHED stable packages ==========================================
FROM base AS hashed_builder
COPY sandbox_reqs_hashed.txt .
RUN pip install \
--prefix=/install/packages \
--require-hashes \
--default-timeout=600 \
--retries 10 \
-r sandbox_reqs_hashed.txt
# === Stage 3: runtime container =======================================================
FROM python:3.11-slim AS sandbox-runtime
WORKDIR /app
ENV PYTHONUNBUFFERED=1
# --- Install minimal OS dependencies ---
RUN apt-get update && apt-get install -y --no-install-recommends \
libgl1 \
libglib2.0-0 \
firejail \
libmagic1 \
supervisor \
sudo \
curl \
wget \
vim \
nano \
less \
net-tools \
iproute2 \
man-db \
locales \
htop \
iputils-ping \
nmap \
netcat-openbsd \
dnsutils \
tcpdump \
whois \
traceroute \
procps \
git \
build-essential \
libjpeg-dev \
libpng-dev \
libfreetype6-dev \
libopenblas-dev \
liblapack-dev \
libxml2-dev \
libxslt1-dev \
libffi-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY docker/sandbox/computer_shell_netfilter.conf /app/computer_shell_netfilter.conf
# --- Create a restricted sandbox user ---
RUN useradd -ms /bin/bash sandboxuser && \
echo 'sandboxuser ALL=(ALL) NOPASSWD: /usr/bin/firejail /bin/bash, /usr/bin/firejail /usr/bin/apt-get *, /usr/bin/firejail /usr/bin/pip' \
> /etc/sudoers.d/sandboxuser && \
chmod 440 /etc/sudoers.d/sandboxuser
# --- Prepare app directory ---
RUN mkdir -p /app /var/log/supervisor && \
chown -R sandboxuser:sandboxuser /app /var/log/supervisor
# --- Copy installed packages from both build stages ---
# NOTE: these two layers are merged into /usr/local sequentially.
# If both stages resolve different versions of the same package, the compiled
# C extensions (.so files) and pure-Python files can end up mismatched.
# The force-reinstall step below fixes any such collisions.
COPY --from=unhashed_builder /install/packages /usr/local
COPY --from=hashed_builder /install/packages /usr/local
# --- Resolve package version conflicts introduced by the two-stage merge ---
# charset-normalizer is the known offender: the unhashed and hashed stages can
# resolve different versions whose compiled C extensions (.so) and pure-Python
# files end up mismatched after the sequential COPY. Force a clean reinstall
# to get a single coherent wheel.
RUN pip install --force-reinstall --no-cache-dir charset-normalizer
# --- Copy sandbox app code ---
COPY src/api/sandbox /app/sandbox
# --- Utilities ---
COPY docker/common/wait-for-it.sh /app/wait-for-it.sh
COPY docker/sandbox/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN chmod +x /app/wait-for-it.sh
# --- Expose sandbox FastAPI server port ---
EXPOSE 8000
# --- Default command ---
CMD ["/usr/bin/supervisord", "-n"]