This README describes utilities to download and run SageMath containers under Ubuntu Linux under WSL2 using Podman. A podman-compose script handles downloading SageMath containers and mounts container directories on the host system for Jupyter notebook access and configuration. Shell scripts automate starting and stopping the container, and provide interactive container access.
SageMath is an open-source mathematics software system. Running it in a container provides:
- Isolation from host system dependencies
- Consistent environment across different machines
- Simplified deployment and version management
Containerizing SageMath presents specific challenges with file permissions when mounting host volumes for persistent storage of notebooks.
- Ubuntu 24.04 or similar Linux distribution (works with WSL2)
- Podman installed
- Python 3.x (for podman-compose)
- SageMath container image from Docker Hub
This setup uses podman-compose in a Python virtual environment. The repository includes a venvfix.sh
script to simplify the setup process:
# Make the script executable
chmod +x venvfix.sh
# Run the script to set up the virtual environment
./venvfix.sh
# Activate the virtual environment
source bin/activate
The script will:
- Remove any existing virtual environment components
- Create a new virtual environment
- Upgrade pip, setuptools, and wheel
- Install all dependencies from requirements.txt
Remember to activate the virtual environment before running podman-compose commands.
This containerized SageMath setup uses bind mounts to share directories between the host and container. Bind mounts directly map host directories to container directories, enabling persistent storage of notebooks and configurations.
Podman implements user namespaces as a security feature, which isolates users in the container from users on the host system. With user namespaces:
- Inside the container, SageMath runs as the
sage
user (UID/GID 1000:1000) - On the host, Podman maps this container user to a high-numbered UID (typically 100999:100999)
The bind mount options (:Z,U
) in the configuration ensure proper file access across this namespace boundary. The Z
option handles SELinux contexts, while the U
option maintains the correct user mapping between container and host.
The repository includes a podman-compose.yml
file with the following configuration:
version: '3.8'
services:
sagemath:
image: docker.io/sagemath/sagemath:latest
container_name: sagemath
user: "1000:1000"
ports:
- "8888:8888"
command: sage-jupyter
volumes:
- ~/Jupyter:/home/sage/notebooks:Z,U
- ~/.jupyter:/home/sage/.jupyter:Z,U
networks:
default:
driver: bridge
Key elements:
- Sets container user to 1000:1000 (matches sage user in container)
- Maps port 8888 for Jupyter access
- Uses bind mounts with
:Z,U
options where:Z
enables SELinux relabeling for container accessU
applies the container's UID/GID mapping to the bind mount
The user: "1000:1000"
line should match the UID:GID of the sage user in the container. Additionally, you should verify that this matches your host system user:
id $USER
If your host user's UID:GID does not match 1000:1000, you have two options:
- Update the podman-compose.yml to match your host user's UID:GID
- Keep 1000:1000 and create a matching sage user on the host (recommended if the container's sage user is fixed at 1000:1000)
For most standard Linux installations, the first user account is assigned 1000:1000, but this may vary.
To align file ownership on the host, create a matching sage
user and group:
# Create the sage group with GID 100999
sudo groupadd -g 100999 sage
# Create the sage user with UID 100999 and primary group sage
sudo useradd -u 100999 -g 100999 -s /bin/bash -m sage
# Add your user to the sage group for file access
sudo usermod -a -G sage $USER
# Create the Jupyter directory if it doesn't exist
mkdir -p ~/Jupyter
# Set appropriate permissions on the Jupyter directory
sudo chown sage:sage ~/Jupyter
sudo chmod 775 ~/Jupyter
This creates a user outside the normal UID range that matches Podman's namespace mapping.
-
Avoid creating a
/home/$USER/.config/containers/containers.conf
file withuserns = "keep-id"
as this conflicts with the compose file settings. -
The high UID (100999) is outside the normal range to prevent conflicts with system-assigned UIDs.
-
When creating the user, you'll see a message:
useradd warning: sage's uid 100999 outside of the UID_MIN 1000 and UID_MAX 60000 range.
This is expected.
The repository includes these helper scripts:
man-up.sh - Start the container and follow logs:
#!/bin/bash
podman-compose -f ~/sagepod/podman-compose.yml up -d && podman logs -f sagemath
man-down.sh - Stop the container:
#!/bin/bash
podman-compose -f ~/sagepod/podman-compose.yml down
run-bash.sh - Start a bash shell in the running container:
#!/bin/bash
podman exec -it sagemath /bin/bash
Make sure to make the scripts executable:
chmod +x man-up.sh man-down.sh run-bash.sh
# Activate the virtual environment if not already activated
source ~/sagepod/bin/activate
# Start the container and follow logs
./man-up.sh
# In a different terminal, you can enter the container with
./run-bash.sh
# To stop the container
./man-down.sh
Access Jupyter at http://localhost:8888
in your browser.
With this bind mount configuration:
- Inside container: Files appear as sage:sage (1000:1000)
- On host: Files appear as sage:sage (100999:100999)
This user namespace mapping allows Jupyter to read and write notebooks without permission errors.
After setting up and running the container for the first time, verify the file ownership on the host:
ls -la ~/Jupyter/
You should see files owned by sage:sage. If you see numeric UIDs instead (like 100999:100999), it confirms that Podman is mapping the UIDs correctly, but the sage user has not been properly created on the host. In this case, revisit the "Host System Configuration" section.
If you see different UIDs, you may need to adjust the UID:GID values in your setup to match what Podman is using in your specific environment.
If you encounter read-only notebooks or permission errors:
- Verify you've added your user to the sage group
- Check that no conflicting containers.conf file exists
- Ensure the Jupyter directory exists on your host before starting the container
- You may need to log out and back in for group changes to take effect
If you encounter issues with podman-compose:
- Ensure the virtual environment is activated with
source ~/sagepod/bin/activate
- Verify all dependencies are installed with
pip list | grep podman-compose
- Try updating dependencies with
pip install --upgrade podman-compose podman
- Check the helper scripts have proper paths for your environment
- SageMath Documentation
- Jupyter Notebook Documentation
- Podman Documentation
- Podman-Compose GitHub Repository
This documentation is provided under the MIT License.