# Switch between Docker and Apptainer ## Goal Choose whether PlayMolecule executes app containers with Docker or Apptainer. ## Minimal example ```bash export PM_RUNTIME=docker # default # or export PM_RUNTIME=apptainer ``` The setting takes effect on the next `import playmolecule`. ## When to use which | Runtime | Choose when | |------------|------------------------------------------------------------------------------------------------------| | `docker` | You're on a workstation or VM. Your user can `docker run` without `sudo`. | | `apptainer`| You're on a shared HPC node where the cluster policy forbids Docker, or you can't get root help to add yourself to the `docker` group. | For SLURM workers, Apptainer is almost always the only viable choice. ## What changes under the hood - **`docker`** — PlayMolecule shells out to the `docker` CLI, pulling images from the registry into the daemon's image store. Containers are launched with `docker run`. - **`apptainer`** — PlayMolecule converts each Docker image into a plain SIF file once (via `apptainer pull docker://...`, cached under `PM_SIF_CACHE_DIR`, default `~/.cache/playmolecule/apptainer/`), then runs `apptainer run` against the SIF. The image content is identical; the runtime and packaging differ. ## Apptainer prerequisites You need a working `apptainer`. On modern kernels with user namespaces enabled, that's all — Apptainer runs unprivileged. On older or hardened kernels you may also need the `apptainer-suid` package, which provides a setuid helper as a fallback. ```bash apptainer --version ``` Official install instructions: . ## Custom SIF cache location ```bash export PM_SIF_CACHE_DIR=/scratch/$USER/playmolecule-sif ``` Move the cache off `$HOME` if you're running on a node with a tiny home quota — SIF files for the larger ML apps can be several GB. **On a multi-node cluster, point `PM_SIF_CACHE_DIR` at a path on shared storage** (e.g., `/shared/playmolecule/apptainer/`). The first worker to need an image converts it from Docker once; every subsequent worker — and every other user — reads the same SIF directly. Without a shared cache, every node pulls a fresh copy on first use, which can mean tens of GB of redundant network traffic per app rollout. ## Extracting an artifact in Apptainer mode [Use app artifacts](use-app-artifacts.md) works in either runtime. With Apptainer, `artifact.download()` shells out to `apptainer exec` against the cached SIF; the SIF must exist locally first (it's created automatically the first time you call the app). ## Gotchas - The two runtimes don't share an image cache. Switching mid-workflow re-downloads everything once. - If `apptainer pull docker://...` fails on a hardened node, the kernel may not support user namespaces. Either enable them or install the `apptainer-suid` package as a fallback. PlayMolecule itself never calls `sudo`. - `docker` mode requires the daemon to be running and the user to be in the `docker` group (or to have sudo without password). ## See also - [Installation](../installation.md) - [Install apps for a cluster](install-apps-for-a-cluster.md) - [Environment variables](../reference/environment-variables.md)