Jumpstart your MLOps projects with this comprehensive Cookiecutter template.
The template provides a robust foundation for building, testing, packaging, and deploying Python packages and Docker images tailored for MLOps tasks.
Related resources:
- MLOps Coding Course (Learning): Learn how to create, develop, and maintain a state-of-the-art MLOps code base.
- MLOps Python Package (Example): Kickstart your MLOps initiative with a flexible, robust, and productive Python package.
- LLMOps Coding Package (Example): Example with best practices and tools to support your LLMOps projects.
- Agent Skills (Resource): Enhance your AI Agents with standardized skills for MLOps and coding.
This Cookiecutter is designed to be a common ground for diverse MLOps environments. Whether you're working with Kubernetes, Vertex AI, Databricks, Azure ML, or AWS SageMaker, the core principles of using Python packages and Docker images remain consistent.
This template equips you with the essentials for creating, testing, and packaging your AI/ML code, providing a solid base for integration into your chosen MLOps platform. To fully leverage its capabilities within a specific environment, you might need to combine it with external tools like Airflow for orchestration or platform-specific SDKs for deployment.
You have the freedom to structure your src/ and tests/ directories according to your preferences. Alternatively, you can draw inspiration from the structure used in the MLOps Python Package project for a ready-made implementation.
- One task vocabulary: mise defines
install,format,check,test,build, and theallgate. Git hooks, CI, and you run the exact same commands — there is no second definition to keep in sync. - Fast, single-tool Python stack: uv for dependencies and packaging, Ruff for linting and formatting (its
S/bandit rules replace a separate security linter), and ty for type checking. - Security in the gate, not beside it: pip-audit for dependency CVEs, gitleaks for secrets, Trivy for the whole checkout, hadolint for the image, and actionlint + zizmor for the workflows.
- Tested by generation, not by inspection:
mise run testbakes a real project into a temporary directory and runs that project's own gate — format, check, test, build, docs, Docker image, and MLflow Projects CLI invocations. - MLflow on a real store: tracking and the model registry use a SQLite database (
sqlite:///mlflow.db), the SQLAlchemy backend MLflow 3 defaults to and a supported local database store for tracking and registry metadata. - Container and CI/CD included: a multi-stage, non-root Docker image, plus GitHub Actions workflows for the gate (
ci.yml), the release (cd.yml: the complete gate, pdoc docs to GitHub Pages, and a scanned image digest promoted to GHCR release tags), and a weekly full-history security rescan (security.yml). - Maintained by default: Dependabot opens grouped security-fix pull requests while version updates stay off, lefthook runs the gate before every commit and push, and git-cliff turns Conventional Commits into a changelog.
- Generate your project:
uvx cookiecutter gh:fmind/cookiecutter-mlops-packageYou'll be prompted for the following variables:
user: Your GitHub username.name: The name of your project.repository: The name of your GitHub repository.package: The name of your Python package.version: The initial version of your project.year: The copyright year written intoLICENSE.txt.description: A brief description of your project.python_version: The Python version to use (e.g., 3.14). It drivesrequires-python, the Ruff target, the ty environment,.python-version, and the Docker base image at once.mlflow_version: The MLflow version to use (e.g., 3.17.0).
The generated project is MIT-licensed. To use another license, replace LICENSE.txt and the license field in pyproject.toml — the template does not ship alternative license texts, so there is no prompt for it.
- Set the project up:
cd <your-repository>
git init # git hooks (lefthook) and secret scanning (gitleaks) need a repository
mise install # download the pinned toolchain (tasks never auto-install it)
mise run install # sync the virtualenv (uv) and install git hooks (lefthook)- Configure the GitHub repository:
- Documentation hosting: go to Settings → Pages and set Source to GitHub Actions. The shipped
cd.ymldeploys through thegithub-pagesenvironment withactions/deploy-pages; it never pushes to a branch, so it does not need "Read and write permissions" under Actions. - Branch protection: run
mise run install:rulesetsto apply.github/rulesets/main.json. It requires thechecksstatus check, which is theci.ymljob name; rename both or neither.
- Explore the generated project:
src/<your-package>/: your Python package source code.tests/: thepytestsuite, with coverage enforced bymise run test.confs/: one config file per MLflow job.Dockerfile/docker-compose.yml: the production image and a local MLflow server.mise.toml: every task;mise taskslists them.
- Start developing:
mise run all # the gate: format, check, test, build
mise run project # invoke the MLflow CLI scaffolds
mise tasks # list everything elseThis repository has two layers, each with its own toolchain: the harness at the root (a pytest-cookies bake suite) and the template sources under {{cookiecutter.repository}}/.
mise install # download the pinned toolchain
mise run install # sync the virtualenv and install git hooks
mise run all # format, check, and test the harnessmise run test is the real proof: it bakes a project into a temporary directory and runs the generated project's own gate inside it, including a Docker build and MLflow Projects CLI invocations. It takes several minutes and needs docker running.
Keep the template in sync with the reference implementation, mlops-python-package: shared configuration files should differ only by their cookiecutter variables. See AGENTS.md for the conventions that keep both layers honest.
We welcome contributions to enhance this Cookiecutter template for generating MLOps projects.
Feel free to open issues or pull requests for any improvements, bug fixes, or feature requests.
This project is licensed under the MIT License. See the LICENSE.txt file for details.
The generated CLI accepts and logs configuration paths; it does not load data, train a model, or run the YAML jobs yet. Implement that logic in src/<package>/scripts.py, using mlops-python-package as the working example. The bake test proves generation, the CLI, MLflow Projects invocation, documentation, and build integration. It does not certify model training or deployment.
Start the local tracking server with mise run docker:compose, which initializes SQLite first. Before using docker compose up directly, run mise run mlflow:db.
When implementing the model workflow, follow the reference package’s PipelineJob: pass selected parameters into training, evaluate its exact registered version, and promote only after thresholds pass. Keep prediction schemas limited to features available at serving time. The generated task remains a CLI scaffold until this logic is implemented.
The release image gate checks vulnerabilities, secrets and misconfigurations. It records license classifications separately: the Debian base includes reciprocal licenses that require an inventory, rather than a blanket license prohibition.