14 KiB
Development Containers
What is a Development Container?
A Development Container (devcontainer) is a containerized development environment that provides:
- ✅ Consistent development environment across all team members
- ✅ Pre-configured tools and dependencies ready to use
- ✅ Instant setup - no manual installation of dependencies
- ✅ Isolated environment that won't conflict with your host system
- ✅ Version-controlled configuration shared with the team
The devcontainer includes Python 3.13, all project dependencies, development tools, and shell customizations pre-installed and configured.
Prerequisites
You need Docker installed on your system:
- Docker Desktop (macOS/Windows)
- Docker Engine (Linux)
Check Docker is working:
docker --version
docker ps
Quick Start (Terminal-First Approach)
1. Clone and Build Container
# Clone the repository
git clone https://git.cleverthis.com/cleverthis/base/base-python
cd base-python
# Build the development container
docker build -f .devcontainer/Dockerfile -t boilerplate-dev .
# Run the development container
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
--name boilerplate-dev \
boilerplate-dev bash
2. Inside the Container
Once inside the container, everything is pre-configured:
# Check Python environment
python --version # Python 3.13.x
which python # /usr/local/bin/python
# Virtual environment is auto-activated
echo $VIRTUAL_ENV # /workspaces/boilerplate/.venv
# Check tools are installed
ruff --version # Linting and formatting
pyright --version # Type checking
behave --version # BDD testing
nox --version # Test automation
# Run development commands
nox -s behave # Run BDD tests
nox -s lint # Run linting
nox -s format # Format code
nox -s typecheck # Type checking
# Test the CLI
python -m boilerplate --name "DevContainer" --count 2
3. Available Shell Aliases
The container includes pre-configured aliases for faster development:
# Development shortcuts
dev-test # nox -s behave
dev-lint # nox -s lint
dev-format # nox -s format
dev-type # nox -s typecheck
dev-docs # nox -s serve_docs
dev-all # nox (run all checks)
# Docker shortcuts
d # docker
build-docker # docker build -t boilerplate:dev .
# Git shortcuts
gs # git status
ga # git add
gc # git commit
gp # git push
gl # git pull
# Python shortcuts
py # python
pip # uv pip (faster package manager)
venv # uv venv
4. Persistent Development
For ongoing development with persistent changes:
# Create a named container for persistence
docker run -it \
-v $(pwd):/workspaces/boilerplate \
-v boilerplate-venv:/workspaces/boilerplate/.venv \
-v boilerplate-cache:/tmp/uv-cache \
-w /workspaces/boilerplate \
--name boilerplate-dev-persistent \
boilerplate-dev bash
# Later, restart the same container
docker start -ai boilerplate-dev-persistent
IDE Integration
Emacs with TRAMP
Connect to your running container from Emacs:
# 1. Start container with SSH (add to Dockerfile if needed)
docker run -it --name boilerplate-dev \
-v $(pwd):/workspaces/boilerplate \
-p 2222:22 \
boilerplate-dev
# 2. In Emacs, connect via TRAMP
# M-x find-file
# /docker:boilerplate-dev:/workspaces/boilerplate/
Emacs Configuration:
;; .emacs or init.el
(require 'tramp)
(setq tramp-default-method "docker")
;; Python development
(use-package python-mode)
(use-package lsp-mode
:hook ((python-mode . lsp)))
(use-package lsp-pyright
:after lsp-mode)
;; Connect to container Python
(setq python-interpreter "/usr/local/bin/python")
Vim/Neovim
Option 1: Terminal Vim Inside Container
# Run container with vim pre-installed
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
boilerplate-dev vim
# Or use neovim if installed
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
boilerplate-dev nvim
Option 2: Host Vim with Container Tools
# 1. Start container as daemon
docker run -d --name boilerplate-tools \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
boilerplate-dev tail -f /dev/null
# 2. Create wrapper scripts
cat > vim-ruff << 'EOF'
#!/bin/bash
docker exec boilerplate-tools ruff "$@"
EOF
chmod +x vim-ruff
# 3. Configure Vim to use container tools
Vim Configuration:
" .vimrc or init.vim
" Python development setup
let g:python3_host_prog = 'docker exec boilerplate-tools python'
" Use container tools for linting
let g:ale_linters = {
\ 'python': ['ruff'],
\}
let g:ale_python_ruff_executable = './vim-ruff'
" Use container tools for formatting
let g:ale_fixers = {
\ 'python': ['ruff'],
\}
VS Code
Option 1: Terminal-First with VS Code Terminal
# 1. Start container
docker run -it --name boilerplate-dev \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
boilerplate-dev bash
# 2. Open VS Code and connect to terminal
# Terminal → New Terminal
# Select "Docker" or connect to running container
Option 2: Dev Containers Extension
# 1. Install Dev Containers extension
# Extensions → Search "Dev Containers" → Install
# 2. Open project folder
code .
# 3. Reopen in container
# Ctrl+Shift+P → "Dev Containers: Reopen in Container"
VS Code Configuration:
The .devcontainer/devcontainer.json is pre-configured with:
- Python 3.13 environment
- 15+ relevant extensions
- Proper settings for ruff, pyright
- Integrated terminal with aliases
- Port forwarding for development servers
PyCharm
Option 1: Remote Python Interpreter
# 1. Start container as daemon
docker run -d --name boilerplate-pycharm \
-v $(pwd):/workspaces/boilerplate \
-p 2222:22 \
boilerplate-dev
# 2. Configure PyCharm remote interpreter
# File → Settings → Project → Python Interpreter
# Add Interpreter → Docker → Existing container
# Container: boilerplate-pycharm
# Python path: /usr/local/bin/python
Option 2: Docker Compose Integration
Create docker-compose.dev.yml:
version: '3.8'
services:
dev:
build:
context: .
dockerfile: .devcontainer/Dockerfile
volumes:
- .:/workspaces/boilerplate
- boilerplate-venv:/workspaces/boilerplate/.venv
working_dir: /workspaces/boilerplate
command: tail -f /dev/null
ports:
- "8000:8000"
- "3000:3000"
volumes:
boilerplate-venv:
# Start development environment
docker-compose -f docker-compose.dev.yml up -d
# PyCharm configuration
# File → Settings → Build, Execution, Deployment → Docker
# Add Docker server (usually auto-detected)
# Configure Python interpreter to use docker-compose service
PyCharm Configuration Steps:
- Settings → Project → Python Interpreter
- Add Interpreter → Docker Compose
- Configuration file:
docker-compose.dev.yml - Service:
dev - Python interpreter path:
/usr/local/bin/python - Apply and OK
What's Included in the Container
🐍 Python Environment
python --version # Python 3.13.x
pip --version # uv-powered pip replacement
which python # /usr/local/bin/python
echo $PYTHONPATH # /workspaces/boilerplate/src
🛠️ Development Tools
ruff --version # Lightning-fast linting and formatting
pyright --version # Strict type checking
nox --version # Test automation across Python versions
behave --version # BDD testing framework
hypothesis --version # Property-based testing
pre-commit --version # Git hooks for code quality
🔧 System Tools
git --version # Git with helpful aliases
docker --version # Docker-in-Docker for building containers
kubectl version --client # Kubernetes CLI
helm version # Helm package manager
gh --version # GitHub CLI for repository management
📝 Shell Environment
echo $SHELL # /bin/zsh (Oh My Zsh configured)
alias # List all available aliases
env | grep PYTHON # Python-related environment variables
Advanced Usage
Port Forwarding
Forward ports from container to host:
# Forward development server ports
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
-p 8000:8000 \
-p 3000:3000 \
-p 8080:8080 \
boilerplate-dev bash
# Now you can access:
# http://localhost:8000 - Application server
# http://localhost:3000 - MkDocs development server
# http://localhost:8080 - Development server
Volume Mounts for Performance
For better performance, especially on macOS/Windows:
# Use named volumes for dependencies
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-v boilerplate-venv:/workspaces/boilerplate/.venv \
-v boilerplate-cache:/tmp/uv-cache \
-v boilerplate-node-modules:/workspaces/boilerplate/node_modules \
-w /workspaces/boilerplate \
boilerplate-dev bash
Custom Configuration
Mount custom configuration files:
# Mount custom git config
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-v ~/.gitconfig:/home/vscode/.gitconfig:ro \
-v ~/.ssh:/home/vscode/.ssh:ro \
-w /workspaces/boilerplate \
boilerplate-dev bash
# Mount custom shell config
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-v ~/.zshrc:/home/vscode/.zshrc.local:ro \
-w /workspaces/boilerplate \
boilerplate-dev bash
Development Workflow
# 1. Start development container
docker run -it --name dev-session \
-v $(pwd):/workspaces/boilerplate \
-v boilerplate-venv:/workspaces/boilerplate/.venv \
-p 3000:3000 \
-w /workspaces/boilerplate \
boilerplate-dev bash
# 2. Inside container - start documentation server
nox -s serve_docs & # Runs in background
# 3. Make changes to code
vim src/boilerplate/cli.py
# 4. Run tests
dev-test # Quick BDD tests
# 5. Check code quality
dev-lint # Linting
dev-format # Auto-format code
dev-type # Type checking
# 6. Run full test suite
dev-all # All checks
# 7. Exit container (preserves named volumes)
exit
# 8. Later, restart same session
docker start -ai dev-session
GitHub Codespaces Alternative
For cloud-based development without local Docker:
# 1. Go to your GitHub repository
# 2. Click "Code" → "Codespaces" → "Create codespace on main"
# 3. Wait 2-3 minutes for automatic setup
# 4. Everything is pre-configured and ready!
# Inside Codespace, same commands work:
nox -s behave # Run tests
dev-all # Run all checks
python -m boilerplate --help
Codespace Features:
- 🌐 Browser-based: No local setup required
- ⚡ Fast SSD storage: 32GB workspace storage
- 🔄 Persistent: Your work is saved automatically
- 💰 Free tier: 60 hours/month for personal accounts
- 🔒 Secure: Runs in GitHub's infrastructure
Troubleshooting
Container Won't Start
# Check Docker is running
docker --version
docker ps
# Free up disk space
docker system prune -f
# Rebuild container
docker build -f .devcontainer/Dockerfile -t boilerplate-dev . --no-cache
Permission Issues
# Run as your user ID
docker run -it --rm \
-u $(id -u):$(id -g) \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
boilerplate-dev bash
# Or fix permissions after
sudo chown -R $(id -u):$(id -g) .
Tools Not Working
# Check if tools are installed
docker run --rm boilerplate-dev which ruff pyright behave nox
# Check PATH
docker run --rm boilerplate-dev echo $PATH
# Reinstall dependencies
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-w /workspaces/boilerplate \
boilerplate-dev bash -c "uv pip install -e .[dev]"
Performance Issues
# Allocate more resources to Docker
# Docker Desktop → Settings → Resources
# Memory: 4GB+, CPU: 2+ cores
# Use volumes for better performance
docker run -it --rm \
-v $(pwd):/workspaces/boilerplate \
-v boilerplate-cache:/tmp/uv-cache \
-w /workspaces/boilerplate \
boilerplate-dev bash
Best Practices
🔄 Container Lifecycle
# For short tasks - use --rm
docker run --rm boilerplate-dev nox -s lint
# For development sessions - use named containers
docker run --name dev-session boilerplate-dev bash
docker start -ai dev-session # Resume later
📁 Volume Management
# List volumes
docker volume ls
# Clean up unused volumes
docker volume prune
# Backup important data
docker run --rm -v boilerplate-venv:/data -v $(pwd):/backup \
alpine tar czf /backup/venv-backup.tar.gz -C /data .
🔒 Security
# Don't store secrets in container images
# Use environment variables or mounted secrets
docker run -e SECRET_KEY="$SECRET_KEY" boilerplate-dev
# Use read-only mounts when possible
docker run -v $(pwd):/workspace:ro boilerplate-dev
⚡ Performance
# Use named volumes for dependencies
-v boilerplate-venv:/workspaces/boilerplate/.venv
# Enable BuildKit for faster builds
export DOCKER_BUILDKIT=1
docker build -f .devcontainer/Dockerfile -t boilerplate-dev .
# Use multi-stage builds for smaller images (already configured)
Integration with CI/CD
The devcontainer environment matches your CI/CD pipeline exactly:
- ✅ Same Python version (3.13)
- ✅ Same tools (ruff, pyright, behave)
- ✅ Same dependencies (from pyproject.toml)
- ✅ Same commands (nox sessions)
This eliminates "works on my machine" problems completely!
# What works in container will work in CI
dev-all # Local testing
# Same as CI pipeline commands in .forgejo/workflows/ci.yml
Further Reading
Ready to develop? Start with the terminal-first approach and choose your preferred editor integration!