A secure, configurable Python development container for REPL work, scripting, experimentation, and project development.
🚨 Important: The .env file is REQUIRED - the WORKSPACE_PATH variable must be set. Copy .env.example to .env and configure it for your system.
cp .env.example .env
# Edit .env with your workspace path - this is required!Minimum required configuration:
# The only required variable - current directory (.) used as fallback
# Linux/macOS examples:
WORKSPACE_PATH=/home/user/development
# WORKSPACE_PATH=/Users/username/projects
# Windows examples:
# WORKSPACE_PATH=C:/Users/username/development
# WORKSPACE_PATH=C:/dev/projects
# WORKSPACE_PATH=D:/codeOptional configuration with defaults:
PYTHON_VERSION=3.11 # Python version (default: 3.11)
CONTAINER_NAME=python-dev # Container name (default: python-dev-container)
PUID=1000 # User ID (default: 1000)
PGID=1000 # Group ID (default: 1000)
TZ=UTC # Timezone (default: UTC)
# Resource limits (prevents runaway processes)
MEMORY_LIMIT=6400M # Memory limit (default: ~6.4GB)
CPU_LIMIT=3.2 # CPU limit (default: 3.2 cores)Linux/macOS:
# Create and set permissions for your workspace
mkdir -p /home/user/development
sudo chown -R $USER:$USER /home/user/developmentWindows (PowerShell):
# Create workspace directory
New-Item -ItemType Directory -Force -Path "C:\Users\$env:USERNAME\development"
# Windows handles permissions automatically for user directories
# Ensure Docker Desktop has access to the drive in Settings > Resources > File Sharing- Docker Engine or Docker Desktop
- A development workspace directory on your host system
# Start the Python development container
docker compose run --rm python-dev
# Container starts with interactive bash shell in /workspace
# Your host workspace directory is mounted and accessible# Start container
docker compose run --rm python-dev
# Inside container:
python --version # Check Python version
python # Start Python REPL
pip install requests # Install packages
python script.py # Run your scripts
exit # Exit containerSupported Python versions (configure via PYTHON_VERSION):
3.8,3.9,3.10,3.11,3.12,3.13- Slim variants:
3.11-slim,3.12-slim - Alpine variants:
3.11-alpine,3.12-alpine
# Use Python 3.12
PYTHON_VERSION=3.12 docker compose run --rm python-dev
# Use Python 3.11 slim
PYTHON_VERSION=3.11-slim docker compose run --rm python-devFor seamless Git operations, uncomment the git volume mounts in compose.yaml:
# Uncomment these lines in compose.yaml:
# - ${HOME}/.gitconfig:/home/python/.gitconfig:ro
# - ${HOME}/.git-credentials:/home/python/.git-credentials:ro
# - ${HOME}/.ssh:/home/python/.ssh:roThis provides:
- Git configuration: Your identity and settings
- Credentials: Access to private repositories
- SSH keys: Authentication for Git operations
SSH Key Permissions:
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh- Minimal privileges: Runs as non-root user (UID/GID 1000:1000)
- Capability dropping: Only essential capabilities enabled
- No privilege escalation:
no-new-privileges:true - Health monitoring: Automatic Python interpreter health checks
- Configurable capabilities: Documented options for additional permissions
- Resource limits: Prevents runaway processes from consuming all system resources
The container includes only CHOWN by default. Uncomment additional capabilities in compose.yaml if needed:
- DAC_OVERRIDE: Override file access permissions
- FOWNER: File ownership operations
- SETUID/SETGID: Change user/group ID (some package installations)
- NET_BIND_SERVICE: Bind to privileged ports (<1024)
- SYS_PTRACE: Debug/trace processes (debuggers like pdb)
# Start container with your project directory
docker compose run --rm python-dev
# Inside container - your files are in /workspace
cd /workspace
python my_script.py# Start container
docker compose run --rm python-dev
# Install and test packages
pip install pandas numpy
python -c "import pandas; print(pandas.__version__)"# Install and run Jupyter inside container
docker compose run --rm python-dev
# Inside container:
pip install jupyter
jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root# Long-running container for development session
docker compose up -d python-dev
docker compose exec python-dev bash
# Your development session...
# When finished:
docker compose down- PYTHONUNBUFFERED=1: Force Python output to be unbuffered
- PYTHONDONTWRITEBYTECODE=1: Prevent Python from writing .pyc files
- TZ: Timezone for proper timestamp handling
The container includes health checks that verify:
- Python interpreter is accessible
- Python version can be determined
- Basic Python functionality works
Check health status:
docker compose psThe container runs as UID/GID 1000:1000 by default. If you need different user IDs:
# Check your user ID
id
# Set in .env file
PUID=1001
PGID=1001# Ensure workspace is owned by your user
sudo chown -R $USER:$USER /path/to/workspace
# Check container user matches your user
id# Ensure SSH key permissions
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh
# Test SSH connection
ssh -T git@github.comUncomment additional capabilities in compose.yaml if package installation fails:
cap_add:
- CHOWN
- SETUID # Uncomment for package installations
- SETGID # Uncomment for package installationsPython processes can consume large amounts of resources. Adjust limits in .env:
# For memory-intensive tasks (ML, data processing)
MEMORY_LIMIT=12G
CPU_LIMIT=6.0
# For resource-constrained systems
MEMORY_LIMIT=2G
CPU_LIMIT=1.0Auto-detect your system limits:
# Memory (80% of total)
echo "MEMORY_LIMIT=$(($(grep MemTotal /proc/meminfo | awk '{print $2}') * 80 / 100 / 1024))M"
# CPU (80% of total)
echo "CPU_LIMIT=$(echo "$(nproc) * 0.8" | bc)"
# Windows PowerShell equivalents:
# Memory (80% of total)
$totalMem = [math]::Round((Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb * 0.8, 1)
Write-Host "MEMORY_LIMIT=${totalMem}G"
# CPU (80% of total)
$totalCPU = [math]::Round($env:NUMBER_OF_PROCESSORS * 0.8, 1)
Write-Host "CPU_LIMIT=$totalCPU"Volume Mount Problems:
# Ensure Docker Desktop has drive access
# Settings > Resources > File Sharing > Add your drive (C:, D:, etc.)
# Check if path exists and is accessible
Test-Path "C:\Users\$env:USERNAME\development"
# Use forward slashes in .env file (Docker prefers this)
# WORKSPACE_PATH=C:/Users/username/development # Good
# WORKSPACE_PATH=C:\Users\username\development # May cause issuesPermission Issues on Windows:
# Check current user has access
Get-Acl "C:\Users\$env:USERNAME\development" | Format-List
# If using WSL2, ensure path is accessible from WSL
wsl ls -la /mnt/c/Users/$USER/developmentLinux/macOS:
# .env configuration
WORKSPACE_PATH=/home/user/data-analysis
PYTHON_VERSION=3.11
# Start container and install data stack
docker compose run --rm python-dev
pip install pandas numpy matplotlib jupyter seabornWindows:
# .env configuration
# WORKSPACE_PATH=C:/Users/username/data-analysis
# PYTHON_VERSION=3.11
# Start container and install data stack
docker compose run --rm python-dev
pip install pandas numpy matplotlib jupyter seabornLinux/macOS:
# .env configuration
WORKSPACE_PATH=/home/user/web-projects
PYTHON_VERSION=3.12
# Enable port binding capability in compose.yaml
# Uncomment: NET_BIND_SERVICE
# Start container and install web framework
docker compose run --rm python-dev
pip install flask fastapi uvicornWindows:
# .env configuration
# WORKSPACE_PATH=C:/Users/username/web-projects
# PYTHON_VERSION=3.12
# Enable port binding capability in compose.yaml
# Uncomment: NET_BIND_SERVICE
# Start container and install web framework
docker compose run --rm python-dev
pip install flask fastapi uvicorn