Modernized build tooling
This commit is contained in:
@@ -0,0 +1,595 @@
|
||||
# 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](https://www.docker.com/products/docker-desktop/) (macOS/Windows)
|
||||
- [Docker Engine](https://docs.docker.com/engine/install/) (Linux)
|
||||
|
||||
Check Docker is working:
|
||||
```bash
|
||||
docker --version
|
||||
docker ps
|
||||
```
|
||||
|
||||
## Quick Start (Terminal-First Approach)
|
||||
|
||||
### 1. Clone and Build Container
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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:**
|
||||
```elisp
|
||||
;; .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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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:**
|
||||
```vim
|
||||
" .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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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`:
|
||||
```yaml
|
||||
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:
|
||||
```
|
||||
|
||||
```bash
|
||||
# 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:**
|
||||
1. **Settings** → **Project** → **Python Interpreter**
|
||||
2. **Add Interpreter** → **Docker Compose**
|
||||
3. **Configuration file**: `docker-compose.dev.yml`
|
||||
4. **Service**: `dev`
|
||||
5. **Python interpreter path**: `/usr/local/bin/python`
|
||||
6. **Apply** and **OK**
|
||||
|
||||
## What's Included in the Container
|
||||
|
||||
### 🐍 **Python Environment**
|
||||
```bash
|
||||
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**
|
||||
```bash
|
||||
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**
|
||||
```bash
|
||||
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**
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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**
|
||||
```bash
|
||||
# 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**
|
||||
```bash
|
||||
# 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**
|
||||
```bash
|
||||
# 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**
|
||||
```bash
|
||||
# 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!
|
||||
|
||||
```bash
|
||||
# What works in container will work in CI
|
||||
dev-all # Local testing
|
||||
# Same as CI pipeline commands in .forgejo/workflows/ci.yml
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [Development Containers Specification](https://containers.dev/)
|
||||
- [Docker Best Practices](https://docs.docker.com/develop/dev-best-practices/)
|
||||
- [Container Security Guide](https://docs.docker.com/engine/security/)
|
||||
|
||||
---
|
||||
|
||||
**Ready to develop?** Start with the terminal-first approach and choose your preferred editor integration!
|
||||
Reference in New Issue
Block a user