A Hatch plugin that integrates pycontainer-build to build OCI container images directly from your Hatch projects β no Docker required.
- π Native Hatch Integration - Build containers during
hatch build - π« No Docker Required - Pure Python OCI image generation
- β‘ Fast Builds - Efficient layer caching and reuse
- π§ Configuration via pyproject.toml - Use
[tool.hatch.build.hooks.pycontainer]section - π¦ Automatic Dependency Packaging - Includes project dependencies
- π SBOM Generation - Built-in security compliance
pip install hatch-pycontainerAdd the plugin to your pyproject.toml:
[build-system]
requires = ["hatchling", "hatch-pycontainer"]
build-backend = "hatchling.build"
[tool.hatch.build.hooks.pycontainer]
enable = trueThen build your container:
hatch buildThis will:
- Build your Python package (wheel)
- Create a container image with pycontainer-build
- Output to
dist/image/
[tool.hatch.build.hooks.pycontainer]
# Container image tag
tag = "myapp:latest"
# Base container image
base-image = "python:3.11-slim"
# Include dependencies
include-deps = true[tool.hatch.build.hooks.pycontainer]
# Enable/disable the hook
enable = true
# Skip container build (useful for local dev)
skip = false
# Container image tag
tag = "myapp:v1.0.0"
# Base container image
base-image = "python:3.11-slim"
# Container registry URL
registry = "ghcr.io/user/myapp"
# Push to registry after build
push = false
# Include project dependencies
include-deps = true
# Generate SBOM (spdx or cyclonedx)
sbom = "spdx"
# Enable verbose output
verbose = true
# Disable layer caching
no-cache = false
# Environment variables
[tool.hatch.build.hooks.pycontainer.env]
ENV = "production"
PORT = "8080"
DEBUG = "false"
# Container labels
[tool.hatch.build.hooks.pycontainer.labels]
maintainer = "[email protected]"
org.opencontainers.image.source = "https://github.com/user/repo"# Build both wheel and container
hatch build
# The container image will be at dist/image/[tool.hatch.build.hooks.pycontainer]
tag = "ghcr.io/myorg/myapp:latest"
push = true# Build and push in one command
GITHUB_TOKEN=$GITHUB_TOKEN hatch buildUse environment-specific configuration:
[tool.hatch.envs.default.build.hooks.pycontainer]
tag = "myapp:dev"
base-image = "python:3.11"
push = false
[tool.hatch.envs.production.build.hooks.pycontainer]
tag = "myapp:latest"
base-image = "python:3.11-slim"
push = true
sbom = "spdx"# Skip container build for local dev
hatch build -e local
# Or set in pyproject.toml
[tool.hatch.envs.local.build.hooks.pycontainer]
skip = truename: Build and Release
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install Hatch
run: pip install hatch hatch-pycontainer
- name: Build package and container
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: hatch build# azure.yaml
name: myapp
services:
api:
project: ./
language: python
host: containerapp
hooks:
prebuild:
shell: sh
run: pip install hatch hatch-pycontainer
build:
shell: sh
run: hatch build# .gitlab-ci.yml
build:
image: python:3.11
script:
- pip install hatch hatch-pycontainer
- hatch build
artifacts:
paths:
- dist/- Registers Build Hook - Hatch calls the pycontainer hook during build
- Reads Configuration - Extracts settings from
pyproject.toml - Builds Container - Uses pycontainer-build to create OCI image
- Adds Metadata - Automatically adds version and build info
- Pushes (Optional) - Pushes to registry if configured
[tool.hatch.build.targets.wheel.hooks.pycontainer]
tag = "myapp:wheel-build"
[tool.hatch.build.targets.sdist.hooks.pycontainer]
skip = true # Don't build container for sdist[tool.hatch.build.hooks.pycontainer]
platform = "linux/amd64"
# Note: Full multi-arch builds coming in future releasepycontainer-build automatically detects:
- FastAPI - Configures uvicorn entrypoint
- Flask - Sets up Flask server
- Django - Configures Django runserver
[tool.hatch.build.hooks.pycontainer]
# Minimal distroless image
base-image = "gcr.io/distroless/python3-debian12"
# Alpine for small size
base-image = "python:3.11-alpine"
# Microsoft Azure-optimized
base-image = "mcr.microsoft.com/python/distroless"Set these during build for authentication:
# GitHub Container Registry
GITHUB_TOKEN=ghp_... hatch build
# Docker Hub
REGISTRY_USERNAME=myuser REGISTRY_PASSWORD=mypass hatch build
# Azure Container Registry (uses az cli)
az acr login --name myregistry
hatch buildEnsure the hook is enabled:
[tool.hatch.build.hooks.pycontainer]
enable = true
skip = falseInstall it explicitly:
pip install pycontainer-buildOr add to build requirements:
[build-system]
requires = ["hatchling", "hatch-pycontainer", "pycontainer-build"]Check configuration:
[tool.hatch.build.hooks.pycontainer]
include-deps = trueVerify authentication:
# For GHCR
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
# For ACR
az acr login --name myregistry| Feature | hatch-pycontainer | Dockerfile | Buildpacks |
|---|---|---|---|
| No Docker daemon | β | β | β |
| Pure Python | β | β | β |
| Hatch native | β | β | β |
| Auto-config | β | β | β |
| Layer caching | β | β | β |
| SBOM generation | β | β | β |
- Python 3.11+
- Hatch 1.18.0+
- pycontainer-build (installed automatically)
MIT License - See LICENSE file for details
Contributions welcome! Please see CONTRIBUTING.md for guidelines.
- pycontainer-build - Core container builder
- poetry-pycontainer - Poetry plugin
- Hatch - Modern Python project manager