Sandboxes
Start a sandbox, run code in it, save files to a volume, read them from a second sandbox, and clean up.
A sandbox is an isolated container that you start from Python, run commands in, and terminate when you are done. In this tutorial you will:
You need:
deploy.create and deploy.redeploy permissions. If you created your Chalk
team yourself, you already have them. Otherwise, ask an admin for a role that
includes them. See Permissions.You do not need a Chalk project or chalk init, and you do not deploy anything
with chalk apply. Every sandbox and volume in this tutorial is created by the
tutorial and deleted in the last step.
Set up the Python environment that will run the tutorial:
chalk init already
installed chalkcompute in your project. Start Python from your project
folder with uv run python, or open a Jupyter notebook that uses the
project’s .venv.chalk login, and install chalkcompute with pip install chalkcompute.
Start Python, or a Jupyter notebook, from the folder where you ran
chalk login, so that chalkcompute finds your login. See
Logins and environments.Run each step’s code in one Python session, in order. Later steps use the sandboxes and the volume that earlier steps create.
import chalkcompute
sandbox = chalkcompute.Sandbox(
image=chalkcompute.Image.debian_slim("3.12"),
name="tutorial-first",
).run()
result = sandbox.exec("python3", "--version")
print(result.stdout_text)
Python 3.12.15
run() builds the image, starts the sandbox, and waits until it is ready. The
image here is a slim Debian image with Python 3.12. Chalk caches each image it
builds, so starting another sandbox from the same image skips the build.
exec runs a process inside the sandbox and returns when the process exits.
stdout_text and stderr_text hold everything the process printed.
An image can include Python packages. Start a second sandbox from an image that installs NumPy, and run a line of Python in it:
numpy_sandbox = chalkcompute.Sandbox(
image=chalkcompute.Image.debian_slim("3.12").pip_install(["numpy"]),
name="tutorial-numpy",
).run()
result = numpy_sandbox.exec(
"python3", "-c", "import numpy; print(numpy.arange(10).sum())"
)
print(result.stdout_text)
45
The first time Chalk builds an image, run() waits for the build, which can
take a few minutes.
The first sandbox is still running. Terminate both, since the next steps start new ones:
sandbox.terminate()
numpy_sandbox.terminate()
When a sandbox terminates, its filesystem is deleted with it. To keep a file after the sandbox is gone, save it to a volume.
Create a volume named tutorial-notes by uploading a file to it from your
machine:
volume = chalkcompute.Volume("tutorial-notes")
volume.put_file("from-my-machine.txt", b"Uploaded from my machine\n")
Volume("tutorial-notes") does not contact Chalk by itself. The volume is
created the first time you read or write through it, here with put_file.
Now start a sandbox with the volume mounted at /data, and write a second file
from inside it. Inside the sandbox, the volume is an ordinary directory:
writer = chalkcompute.Sandbox(
image=chalkcompute.Image.debian_slim("3.12"),
name="tutorial-writer",
volumes=[("tutorial-notes", "/data")],
).run()
writer.exec("sh", "-c", "echo 'Saved by tutorial-writer' > /data/note.txt")
result = writer.exec("/data/.chalk-volume/commit")
print(result.stdout_text)
writer.terminate()
published Chalk Volume version 2
Writes to a mounted volume stay inside the sandbox until they are committed.
/data/.chalk-volume/commit commits them and waits until the volume has saved
them as a new version. A sandbox also commits its writes when it terminates, but
that final commit has a time limit, so commit before you terminate a sandbox
whose writes you need. For the other ways to commit, see
Syncing a mounted volume.
The writer is gone, and its file is still on the volume. Start a new sandbox with the same volume mounted, and read both files:
reader = chalkcompute.Sandbox(
image=chalkcompute.Image.debian_slim("3.12"),
name="tutorial-reader",
volumes=[("tutorial-notes", "/data")],
).run()
result = reader.exec("sh", "-c", "cat /data/from-my-machine.txt /data/note.txt")
print(result.stdout_text)
Uploaded from my machine
Saved by tutorial-writer
Any number of sandboxes can mount the same volume. Each one sees the volume’s latest committed version when it starts.
Terminate the reader and delete the volume:
reader.terminate()
volume.delete()
delete() removes the volume and every version of it. The sandboxes from the
earlier steps were terminated when you finished with them, so nothing from this
tutorial is left running.
exec_stream, or send input with exec_start