Build your own container image with Enroot
Enroot is a container runtime. It builds and runs the container images that Pyxis uses in your SLURM jobs.
If the pre-built images don't have what you need, build your own with Enroot.
Note
Build your custom image in a normal login session, not inside a SLURM job. Customizing an image doesn't need the GPU. You'll get GPU access later, when you run the finished image in a job.
A login session shares a limited memory budget with every other logged-in
user — see What you can't do in a login
session. If your
customization needs more memory than that budget allows, for example
installing a large package or compiling something, run the same steps
inside a job instead. Skip --gres=gpu, since you still don't need the
GPU:
Then follow the steps below inside that shell.
Import a base image¶
Pull an image from a registry. Enroot converts it into a .sqsh file:
This creates a .sqsh file in your current directory, named after the
image — in this example, nvidia+pytorch+26.07-py3.sqsh. A .sqsh file is
a single, compressed, read-only image of the container's filesystem. Enroot
uses this format to store and run container images.
Note
While it builds the image, Enroot also needs temporary disk space under
~/.cache/enroot-tmp — roughly as much as the uncompressed image, on top
of the final .sqsh file. This counts against your storage
quota, so a large import can fail if
you're close to your limit.
If an import is interrupted, for example your connection drops, Enroot
can leave files behind in ~/.cache/enroot-tmp. Check with du -sh
~/.cache/enroot-tmp and remove them with rm -rf ~/.cache/enroot-tmp/*
to free the space back up.
Open a writable session¶
Creating a container from the image and starting it are two separate steps:
-
Create a container from the image:
-
Start it with a writable filesystem:
Add
--roottoo if you plan to install an Ubuntu package withaptin step 3 — without it, you don't have permission to write to the system directoriesaptneeds:NVIDIA_VISIBLE_DEVICES=voidstarts the container even though the GPU isn't available in a login session. You'll still see warnings and errors about GPU functionality — ignore them:Expected warnings and errors[10-nvidia-mps.sh] WARNING: MPS control socket not found at /tmp/nvidia-mps/control [10-nvidia-mps.sh] Ensure nvidia-cuda-mps.service is running on the host ... ERROR: The NVIDIA Driver is present, but CUDA failed to initialize. GPU functionality will not be available. [[ Unable to initialize CUDA driver (error ???) ]] Failed to detect NVIDIA driver version.You'll see a prompt like this once you're inside the container:
With
--root, the prompt showsrootin place of your username. -
Make your changes inside the session. For example, install a Python package with
pip:Or install an Ubuntu package with
apt(needs the container started with--root, as shown above):
Save your changes¶
Export the container to a .sqsh file:
Check that the custom image preserved your changes¶
-
Create a container from
custom.sqsh: -
Start it, again with
NVIDIA_VISIBLE_DEVICES=void: -
Check that your changes are still there. If you installed
plotlywithpip:You should see:
If you installed
graphvizwithapt, check:You should see:
Remove containers you no longer need¶
Enroot doesn't remove containers when you exit them. They stay in
~/.local/share/enroot/ and keep using disk space until you remove them.
List your active containers:
Remove one by name:
For example, to remove the containers from this guide:
This only removes the containers. Your custom image is still saved as a
.sqsh file — use it to create a new container with Enroot, or run a job
with Pyxis.
Use your image in a job¶
Set --container-image to your saved image. Use it the same way as a
pre-built image:
srun --gres=gpu:1 --container-image=./custom.sqsh python -c "import plotly; print(f'plotly version: {plotly.version}')"
Note
The ./ in --container-image=./custom.sqsh tells Pyxis to load the
image from the current directory, instead of looking for it in the
public registry. You can also use the full path:
--container-image=/home/<username>/custom.sqsh.