Reproducible, robust, and yet simple development setup for Python. Developing in VSCode Dev Containers.
Takes only three steps.
- Clone the repo
# Clone the repo
# Or use GitHub's "Use this template" button
# Or use GitHub CLI: gh repo create <your-project-name> --template <this-repo>
git clone <this-repo> <your-project-name>
cd <your-project-name>
# change remote url to your repo
git remote set-url origin git://new.url.here- Replace Placeholders
- Replace
my_projectindocker-compose.ymlwith your project name - Replace
python-project-templateinpyproject.tomlwith your project name; updatenameandversion - Update the year and copyright holder in
LICENSE - Update this
README.mdfor your project.
- Open in VS Code & Dev Container
# Open project folder in VS Code
code .
# When prompted, or using the Command Palette (Ctrl+Shift+P), select:
# > Dev Containers: Open Folder in Container (or similar)
# after build you should see
# CTRL+p > Python: Select Interpreter > /home/nonroot/.venv/bin/python (as defined in `Dockerfile`)- Add dependencies:
uv add <package-name>(runs inside the container) pre-commit(linting, formatting, testing) runs automatically on commit- want to ignore files that are specific to you without using
.gitignore? Add them to.git/info/exclude
Want to use an already authenticated az cli from the host?
Add this to the following files:
// .devcontainer/devcontainer.json
"features": {
...
// ADD THIS
"ghcr.io/devcontainers/features/azure-cli:1": {}
}You can add this, to ensure you are logged in as your user. Or you can just run az login. This will open a browser so you can login. The cache credentials will be local to the devcontainer which means you can be logged in to different tenants in different devcontainers.
# .devcontainer/docker-compose.extend.yml
volumes:
...
// ADD THIS
- ${HOME}/.azure:/home/nonroot/.azure:rwThis template uses VSCode's Dev Containers with Docker Compose:
docker-compose.ymlconfigures services like backend or database- mounts your local project directory into the container, so you can edit files locally in VSCode while staying them in a container environment
This approach ensures that all developers work with identical dependencies and configurations, regardless of their host machine.
- Simplicity first: keep functions small, clear, and free of bloat.
- Clarity > cleverness: readable names and explicit logic beat tricks.
- YAGNI: implement only today’s requirements; postpone “nice-to-haves.”
- Single responsibility: one purpose per module, class, and function.
- Composition over inheritance: favour plain objects; if an interface is needed, use an
ABC, not aProtocol. - Pythonic, not painful: embrace idioms without overcomplicating code.
- Fail fast & loud: validate inputs early and raise clear errors.
- Typed & documented: PEP 484 type hints + Google-style docstrings.
- Testable by design: write pytest-ready, side-effect-free units.
- Immutable by default: fewer surprises, safer concurrency.
- Dependency discipline: keep
pyproject.tomllean and current. - Secure defaults: load secrets from env vars; least-privilege access.
- Measure before tuning: profile first, optimise real hotspots only.
- Continuous refactor: pay technical-debt in small, frequent steps.
uvfor dependency management- VS Code devcontainers with
docker compose-file - Multi-stage build with
builder, also used for development, andproduction - web framework example:
fastapiwithuvicorn(exampleGET /endpoint insrc/main.py) - debugging:
debugpy - testing:
pytest - linting & formatting:
ruff - type-checking:
mypy - environment variables:
python-dotenv pre-commithooks
- write commits following The seven rules of a great commit message: *What- and *why- in imperative mood instead of how
- follow 12-factor principles
- agree on git workflow, for example trunk-based development
- Use multi-stage builds to structure docker images and only include the needed runtime dependencies for smaller image size and faster builds and fewer attack vectors
- Follow a styleguide like Google Python Style Guide
- Tag releases with SemVer:2.0.0 or CalVer
- For a changelog, adapt principles of common-changelog, written by humans for humans, a clean git history as foundation
- release with tags and changelog using
git-release AGENTS.md: Best practices on writing customer instructions for Github Copilot
See Dockerfile-advanced-notes.md for an annotated multi-stage build example covering the builder and production stages.