Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions docs/e2b.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ for the truth.
## The code-interpreter flavor

`e2b-ci` is built from e2b's own recipe, `e2b-dev/code-interpreter`
`template/` at `f56a1edf75`, vendored under `os-image/e2b-ci/code-interpreter/`
with its license. On top of `e2b-rt`'s contents it runs a Jupyter server on
`template/` at the `CI_RECIPE_SHA` the Dockerfile pins: the build fetches that
commit's archive, checks its sha256, and applies the one local change listed in
`os-image/e2b-ci/PATCHES`; e2b's license ships in the image under
`/usr/share/doc/e2b-code-interpreter/`. Moving to a newer recipe is a bump of the
two `CI_RECIPE_*` args plus a refresh of the constraints files. On top of `e2b-rt`'s contents it runs a Jupyter server on
loopback 8888 and the code-interpreter API on 49999, both enabled at boot, and
the guard drops off-guest traffic to 49983, 49999 and 8888. Only the python
kernel ships: the recipe installs its javascript, R and Java kernels from
Expand All @@ -74,7 +77,10 @@ dependency, moving release archives), so they wait for a reproducible source.

Every pip dependency is pinned by `constraints.txt` and `server-constraints.txt`
beside the Dockerfile, and bytecode is compiled hash-checked at the end, so a
rebuild of one commit against the same base yields the same layer.
rebuild of one commit against the same base yields the same layer. That holds
for the OCI and registry exporters with `SOURCE_DATE_EPOCH` and
`rewrite-timestamp=true`, as the image workflow builds; the `docker` exporter
ignores `rewrite-timestamp`, so a local reproducibility check exports OCI.

The pool's warmup waits on both daemons:

Expand Down
40 changes: 25 additions & 15 deletions os-image/e2b-ci/24.04/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
# e2b's code interpreter on the e2b data plane: envd, a Jupyter server and the
# code-interpreter API on 49999, both started at boot. The recipe is
# e2b-dev/code-interpreter template/ at f56a1edf75, vendored under
# code-interpreter/ with its LICENSE; constraints.txt and
# server-constraints.txt pin the full sets it resolves to, so a rebuild of one
# commit installs the same packages. Python kernel only: the recipe's
# javascript, R and Java kernels install from unpinned sources.
# e2b-dev/code-interpreter template/ at CI_RECIPE_SHA, fetched and checksummed
# here, with PATCHES applied; constraints.txt and server-constraints.txt pin the
# full sets it resolves to, so a rebuild of one commit installs the same
# packages. Python kernel only: the recipe's javascript, R and Java kernels
# install from unpinned sources.
#
# amd64 only: e2b publishes no arm64 build of envd.
ARG BASE_IMAGE=ghcr.io/cocoonstack/sandbox/base:24.04
ARG ENVD_VERSION=v0.8.0
ARG ENVD_SHA256=752cfbc7ba66649ec1bffdc9b59529dd3527e7d3899c69351e05bd21dfc0dbf0
ARG CI_RECIPE_SHA=f56a1edf750e20a96f847df57e0063eeeb5e13c3
ARG CI_RECIPE_SHA256=3af064c471e41f72a3c56920f61219c4259ef4aacf466f3e8687b5af30d68c48

FROM ${BASE_IMAGE} AS src
ARG ENVD_VERSION
ARG ENVD_SHA256
ARG CI_RECIPE_SHA
ARG CI_RECIPE_SHA256
ENV DEBIAN_FRONTEND=noninteractive
# [repro] nothing writes a .pyc until compileall writes them all, hash-checked and with fixed set order.
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONHASHSEED=0

COPY code-interpreter /tmp/ci
COPY constraints.txt server-constraints.txt /tmp/ci/
COPY constraints.txt server-constraints.txt javascript-context.patch /tmp/ci/
COPY systemd/jupyter.service systemd/code-interpreter.service /etc/systemd/system/

RUN curl -fsSL -o /usr/local/bin/envd \
Expand All @@ -28,8 +31,14 @@ RUN curl -fsSL -o /usr/local/bin/envd \
chmod 0755 /usr/local/bin/envd && \
echo "${ENVD_VERSION#v}" > /etc/envd-version && \
apt-get update && apt-get install -y --no-install-recommends \
nftables sudo jq util-linux fonts-noto-cjk build-essential \
nftables sudo jq util-linux fonts-noto-cjk build-essential patch \
python3 python3-venv python3-dev && \
curl -fsSL -o /tmp/ci/recipe.tar.gz \
"https://github.com/e2b-dev/code-interpreter/archive/${CI_RECIPE_SHA}.tar.gz" && \
echo "${CI_RECIPE_SHA256} /tmp/ci/recipe.tar.gz" | sha256sum -c - && \
tar -xzf /tmp/ci/recipe.tar.gz -C /tmp/ci --strip-components=1 \
"code-interpreter-${CI_RECIPE_SHA}/template" "code-interpreter-${CI_RECIPE_SHA}/LICENSE" && \
patch -d /tmp/ci -p1 < /tmp/ci/javascript-context.patch && \
# [envd] loopback only, as in e2b-rt; uvicorn binds the interpreter API to 0.0.0.0 too.
printf '%s\n' \
'table inet e2bguard {' \
Expand Down Expand Up @@ -75,17 +84,18 @@ RUN curl -fsSL -o /usr/local/bin/envd \
useradd -m -s /bin/bash user && \
echo 'user ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/user && chmod 0440 /etc/sudoers.d/user && \
python3 -m venv /opt/python && \
/opt/python/bin/pip install --no-cache-dir --no-compile -r /tmp/ci/requirements.txt -c /tmp/ci/constraints.txt && \
/opt/python/bin/pip install --no-cache-dir --no-compile -r /tmp/ci/template/requirements.txt -c /tmp/ci/constraints.txt && \
/opt/python/bin/python -m ipykernel install --sys-prefix --name python3 && \
mv /tmp/ci/server /root/.server && \
mv /tmp/ci/template/server /root/.server && \
python3 -m venv /root/.server/.venv && \
/root/.server/.venv/bin/pip install --no-cache-dir --no-compile -r /root/.server/requirements.txt -c /tmp/ci/server-constraints.txt && \
/opt/python/bin/python -m compileall -q -f -j 1 --invalidation-mode unchecked-hash /opt/python/lib /root/.server && \
install -D -m 0644 /tmp/ci/matplotlibrc /root/.config/matplotlib/.matplotlibrc && \
install -D -m 0755 /tmp/ci/jupyter-healthcheck.sh /root/.jupyter/jupyter-healthcheck.sh && \
install -D -m 0644 /tmp/ci/jupyter_server_config.py /root/.jupyter/jupyter_server_config.py && \
install -D -m 0644 /tmp/ci/ipython_kernel_config.py /root/.ipython/profile_default/ipython_kernel_config.py && \
install -D -m 0644 -t /root/.ipython/profile_default/startup /tmp/ci/startup_scripts/*.py && \
install -D -m 0644 /tmp/ci/template/matplotlibrc /root/.config/matplotlib/.matplotlibrc && \
install -D -m 0755 /tmp/ci/template/jupyter-healthcheck.sh /root/.jupyter/jupyter-healthcheck.sh && \
install -D -m 0644 /tmp/ci/template/jupyter_server_config.py /root/.jupyter/jupyter_server_config.py && \
install -D -m 0644 /tmp/ci/template/ipython_kernel_config.py /root/.ipython/profile_default/ipython_kernel_config.py && \
install -D -m 0644 -t /root/.ipython/profile_default/startup /tmp/ci/template/startup_scripts/*.py && \
install -D -m 0644 /tmp/ci/LICENSE /usr/share/doc/e2b-code-interpreter/LICENSE && \
systemctl enable envd-guard.service envd.service jupyter.service code-interpreter.service && \
rm -rf /tmp/* /var/lib/apt/lists/* /var/log/apt /var/log/dpkg.log /var/log/alternatives.log \
/var/cache/ldconfig/aux-cache /var/cache/debconf/*-old /root/.cache
Expand Down
5 changes: 5 additions & 0 deletions os-image/e2b-ci/PATCHES
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
javascript-context.patch applies to e2b-dev/code-interpreter at CI_RECIPE_SHA
and is re-applied on every recipe bump. template/server/main.py creates the
default javascript context only when Jupyter lists a javascript kernelspec;
this flavor ships the python kernel alone, and upstream's server otherwise
fails its startup on the missing kernel.
201 changes: 0 additions & 201 deletions os-image/e2b-ci/code-interpreter/LICENSE

This file was deleted.

7 changes: 0 additions & 7 deletions os-image/e2b-ci/code-interpreter/PATCHES

This file was deleted.

Loading
Loading