<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.gacrc.uga.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Kris</id>
	<title>Research Computing Center Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.gacrc.uga.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Kris"/>
	<link rel="alternate" type="text/html" href="https://wiki.gacrc.uga.edu/wiki/Special:Contributions/Kris"/>
	<updated>2026-05-13T03:48:18Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://wiki.gacrc.uga.edu/index.php?title=Podman&amp;diff=22984</id>
		<title>Podman</title>
		<link rel="alternate" type="text/html" href="https://wiki.gacrc.uga.edu/index.php?title=Podman&amp;diff=22984"/>
		<updated>2026-05-06T21:01:33Z</updated>

		<summary type="html">&lt;p&gt;Kris: Add Podman page!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Podman is available on Sapelo2 for researchers who need to run software distributed as [https://opencontainers.org/ OCI container images]. It can be useful when a project already provides a standard container image or when a workflow expects familiar Docker-style commands. [https://developers.redhat.com/blog/2020/09/25/rootless-containers-with-podman-the-basics Podman is provided in a rootless configuration] and behaves differently from a typical workstation or server installation. In particular, image storage and some runtime features are constrained by the cluster&#039;s file system and stateless node environment. This guide explains the main differences, why they exist, and the practical limitations users should expect when running Podman on compute nodes.&lt;br /&gt;
&lt;br /&gt;
== Podman in Slurm jobs ==&lt;br /&gt;
Podman depends on &amp;lt;code&amp;gt;XDG_RUNTIME_DIR&amp;lt;/code&amp;gt; (typically &amp;lt;code&amp;gt;/run/user/$UID&amp;lt;/code&amp;gt;) for rootless operation. On Sapelo2, Slurm jobs are not associated with a user systemd session, so this directory is &#039;&#039;&#039;not created automatically&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As a result, Podman will fail in Slurm jobs unless a user session is created. Here is an example error from an interactive job:&amp;lt;syntaxhighlight lang=&amp;quot;shell-session&amp;quot;&amp;gt;&lt;br /&gt;
Failed to obtain podman configuration: lstat /run/user/1337: no such file or directory&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Workaround ===&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Important:&#039;&#039;&#039; Podman will not work in Slurm jobs unless this step is performed.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Before running any Podman commands inside a Slurm job, start a background SSH session to localhost&amp;lt;syntaxhighlight lang=&amp;quot;shell-session&amp;quot;&amp;gt;&lt;br /&gt;
ssh -N localhost &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;This creates a user session in the background and initializes &amp;lt;code&amp;gt;/run/user/$UID&amp;lt;/code&amp;gt;&lt;br /&gt;
This workaround &#039;&#039;&#039;requires passwordless SSH access&#039;&#039;&#039; to your own account. You must have&lt;br /&gt;
&lt;br /&gt;
* An SSH keypair in &amp;lt;code&amp;gt;~/.ssh/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Your public key added to &amp;lt;code&amp;gt;~/.ssh/authorized_keys&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Test with:&amp;lt;syntaxhighlight lang=&amp;quot;shell-session&amp;quot;&amp;gt;&lt;br /&gt;
ssh localhost&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;&#039;This should not prompt for a password.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This works because SSH creates a PAM/systemd user session, which initializes &amp;lt;code&amp;gt;/run/user/$UID&amp;lt;/code&amp;gt;. The session remains active as long as the SSH process is running.&lt;br /&gt;
&lt;br /&gt;
Because the SSH process runs in the background of the job, &#039;&#039;it is automatically cleaned up when the job exits&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Filesystem limitations==&lt;br /&gt;
On Sapelo2, Podman images are effectively &#039;&#039;&#039;node-local&#039;&#039;&#039;, not cluster-global like &amp;lt;code&amp;gt;/apps&amp;lt;/code&amp;gt;. Rootless Podman normally expects local filesystem behavior for its image storage, but NFS-backed &amp;lt;code&amp;gt;/home&amp;lt;/code&amp;gt; and Lustre-backed &amp;lt;code&amp;gt;/scratch&amp;lt;/code&amp;gt; do not provide that behavior. As a result, Podman is configured to use local scratch storage on the compute node where the image is pulled or loaded.&lt;br /&gt;
&lt;br /&gt;
In practice, this means an image you pull on one compute node will not automatically be available on another. Researchers should expect to pull or load images again when moving between nodes.&lt;br /&gt;
&lt;br /&gt;
===Transporting images with &amp;lt;code&amp;gt;podman save&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;podman load&amp;lt;/code&amp;gt;===&lt;br /&gt;
A practical workaround is to save an image as a tar archive on shared storage, then load it into Podman on the node where you want to run it. While this does not make images globally shared, it does make them quicker to move between nodes without re-downloading from a registry on each node.&amp;lt;syntaxhighlight lang=&amp;quot;shell-session&amp;quot;&amp;gt;&lt;br /&gt;
podman pull ubuntu&lt;br /&gt;
podman save -o ubuntu.tar ubuntu&lt;br /&gt;
podman load -i ubuntu.tar&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==NVIDIA Container Toolkit==&lt;br /&gt;
The NVIDIA Container Toolkit is the layer that enables Podman to expose NVIDIA GPUs inside containers. A major feature of the toolkit is CDI, the Container Device Interface. CDI lets containers request GPUs using stable, predictable names such as &amp;lt;code&amp;gt;nvidia.com/gpu=0&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;nvidia.com/gpu=1&amp;lt;/code&amp;gt;, or even &amp;lt;code&amp;gt;nvidia.com/gpu=all&amp;lt;/code&amp;gt;. On a heterogeneous cluster, where GPU types and counts may differ across nodes, this is much simpler than manually listing &amp;lt;code&amp;gt;/dev/nvidia*&amp;lt;/code&amp;gt; devices and host library mounts for each container.&lt;br /&gt;
&lt;br /&gt;
A typical CDI-based Podman command looks like this:&amp;lt;syntaxhighlight lang=&amp;quot;shell-session&amp;quot;&amp;gt;&lt;br /&gt;
podman run --rm --device nvidia.com/gpu=all ubuntu nvidia-smi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===CUDA validation example===&lt;br /&gt;
A practical way to check that CUDA is working inside a container is to run a small PyTorch test rather than relying only on GPU enumeration. In this example, PyTorch reports that CUDA is available, allocates a tensor, and runs a simple arithmetic operation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note:&#039;&#039;&#039; Due to a known issue with the NVIDIA CDI &amp;lt;code&amp;gt;update-ldcache&amp;lt;/code&amp;gt; hook on Sapelo2 (see below), this example includes a manual bind mount of &amp;lt;code&amp;gt;libcuda.so.1&amp;lt;/code&amp;gt;, which would not normally be required.&#039;&#039;&amp;lt;syntaxhighlight lang=&amp;quot;shell-session&amp;quot;&amp;gt;&lt;br /&gt;
$ podman run --rm -it \&lt;br /&gt;
  --device nvidia.com/gpu=all \&lt;br /&gt;
  -v /usr/lib64/libcuda.so.1:/usr/lib/x86_64-linux-gnu/libcuda.so.1:ro \&lt;br /&gt;
  docker.io/pytorch/pytorch:2.9.0-cuda12.8-cudnn9-runtime \&lt;br /&gt;
  python3&lt;br /&gt;
Trying to pull docker.io/pytorch/pytorch:2.9.0-cuda12.8-cudnn9-runtime...&lt;br /&gt;
[output truncated]&lt;br /&gt;
Writing manifest to image destination&lt;br /&gt;
Python 3.11.14 | packaged by conda-forge | (main, Oct 13 2025, 14:09:32) [GCC 14.3.0] on linux&lt;br /&gt;
Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; import torch&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; torch.cuda.is_available()&lt;br /&gt;
True&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; (torch.tensor([1.0], device=&amp;quot;cuda&amp;quot;) * 2).item()&lt;br /&gt;
2.0&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; torch.cuda.get_device_name(0)&lt;br /&gt;
&#039;NVIDIA L4&#039;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; quit()&lt;br /&gt;
$ &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Known Issues ===&lt;br /&gt;
&lt;br /&gt;
==== Broken &amp;lt;code&amp;gt;update-ldcache&amp;lt;/code&amp;gt; OCI hook ====&lt;br /&gt;
The specific hook causing trouble is the NVIDIA CDI &amp;lt;code&amp;gt;update-ldcache&amp;lt;/code&amp;gt; hook. In the generated CDI configuration, that hook appears as a &amp;lt;code&amp;gt;createContainer&amp;lt;/code&amp;gt; hook that invokes &amp;lt;code&amp;gt;/usr/bin/nvidia-cdi-hook&amp;lt;/code&amp;gt; with the &amp;lt;code&amp;gt;update-ldcache&amp;lt;/code&amp;gt; argument. When Podman tries to start a container with CDI enabled, this hook can fail preventing container startup. The &amp;lt;code&amp;gt;update-ldcache&amp;lt;/code&amp;gt; hook is meant to help make host NVIDIA libraries visible inside the container by updating the dynamic linker cache path used by the containerized environment. In a more typical setup, this helps ensure that GPU-related executables inside the container can locate the right shared libraries without extra manual bind mounts. When the &amp;lt;code&amp;gt;update-ldcache&amp;lt;/code&amp;gt; hook fails, CDI may still identify the GPUs correctly, but the automatic library setup path is incomplete. In practice, that means users may need to manually bind-mount some host libraries or utilities into the container instead of relying on the hook to make everything available automatically. &lt;br /&gt;
&lt;br /&gt;
Due to the issues, the &amp;lt;code&amp;gt;update-ldcache&amp;lt;/code&amp;gt; OCI hook has been disabled in CDI. While this avoids container startup failures, it also bypasses the mechanism that updates the container’s dynamic linker cache with host NVIDIA library paths. Consequently, GPU-related libraries may not be discovered automatically inside the container, requiring some manual bind mounts or environment configuration to ensure proper runtime behavior.&lt;br /&gt;
&lt;br /&gt;
This effect is clearly seen in the CUDA validation example above, where &amp;lt;code&amp;gt;libcuda.so.1&amp;lt;/code&amp;gt; is explicitly bind-mounted (&amp;lt;code&amp;gt;-v /usr/lib64/libcuda.so.1:/usr/lib/x86_64-linux-gnu/libcuda.so.1:ro&amp;lt;/code&amp;gt;) despite CDI being enabled via &amp;lt;code&amp;gt;--device nvidia.com/gpu=all&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Kris</name></author>
	</entry>
</feed>