Apptainer Development Layer#
This setup decouples the toolchain from the project workspace.
The Container (
dev.sif): An immutable image containing system libraries and theuvmanager.The Host Workspace: Your project directory containing
pyproject.tomland the.venv.Python Versioning: The container provides a base Python version, but
uv syncmanages the specific version requested in yourpyproject.toml. If your project requires Python 3.12,uvwill download that version into the host-side.venvregardless of the container’s internal 3.13 default.
The Definition File (containers/dev.def)#
Bootstrap: docker
From: python:3.13-slim
%post
# Install system-level tools inside the image
apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates git
rm -rf /var/lib/apt/lists/*
# Install the uv package manager inside the image
curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR="/usr/local/bin" sh
%environment
# Forces the container to prioritize the .venv in the current host directory
export VIRTUAL_ENV="$PWD/.venv"
export PATH="$VIRTUAL_ENV/bin:$PATH"
# Ensures uv manages the Python version within the host-side .venv
export UV_PROJECT_ENVIRONMENT="$VIRTUAL_ENV"
%runscript
# 1. Sync Mode: Triggered by calling the image with no arguments
if [ $# -eq 0 ]; then
if [ -f "pyproject.toml" ]; then
uv sync --group dev
echo ">>> Success: Host .venv synchronized via container."
else
echo ">>> Error: No pyproject.toml found in $PWD."
exit 1
fi
exit 0
fi
# 2. Execution Mode: Passes host commands into the container's context
exec "$@"
Mechanics: How the Layer Functions#
This setup uses Apptainer’s ability to map the host filesystem into the container’s namespace.
File Mapping: Apptainer automatically “bind-mounts” your current directory. Both the host and the container see the same project files.
The “Hollow” Venv: When you run the sync command,
uv(running inside the container) writes the libraries and the requested Python interpreter to the.venvon your host.Path Precedence: The
%environmentblock prepends$PWD/.venv/binto the container’sPATH. When the container executespython, it finds the version in your host’s.venvfirst.Interpreter Execution: The binaries inside the
.venvexecute using the container’s kernel namespace and system-level C libraries.
Usage Workflow#
If your terminal is inside your project root, the commands look like this:
Build the Layer:
apptainer build dev.sif containers/dev.def
Synchronize the Host: Run the image with no arguments to create/update the
.venv.
./dev.sif
Execute through the Layer: Run your code or tests while staying in your host terminal.
./dev.sif python main.py
./dev.sif pytest
Since the .venv is physically located on your host, your IDE can point to it for local syntax highlighting and type checking, while the dev.sif handles the actual execution.