Merge pull request #101 from pratikbin/main

fix: image verities
This commit is contained in:
Tejas Chopra 2026-04-04 11:15:33 -07:00 committed by GitHub
commit ef2d1dc1fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 209 additions and 39 deletions

View file

@ -12,12 +12,31 @@ env:
permissions:
contents: read
packages: write
attestations: write
id-token: write
jobs:
docker:
docker-variant-tags:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- variant: ""
bake_target: runtime
- variant: nonroot
bake_target: runtime-nonroot
- variant: code
bake_target: runtime-code
- variant: code-nonroot
bake_target: runtime-code-nonroot
- variant: slim
bake_target: runtime-slim
- variant: slim-nonroot
bake_target: runtime-slim-nonroot
- variant: code-slim
bake_target: runtime-code-slim
- variant: code-slim-nonroot
bake_target: runtime-code-slim-nonroot
steps:
- uses: actions/checkout@v6
@ -34,34 +53,31 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
- name: Extract metadata (variant)
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
type=ref,event=branch,suffix=${{ matrix.variant != '' && format('-{0}', matrix.variant) || '' }}
type=ref,event=pr,suffix=${{ matrix.variant != '' && format('-{0}', matrix.variant) || '' }}
type=semver,pattern={{version}},suffix=${{ matrix.variant != '' && format('-{0}', matrix.variant) || '' }}
type=semver,pattern={{major}}.{{minor}},suffix=${{ matrix.variant != '' && format('-{0}', matrix.variant) || '' }}
type=semver,pattern={{major}},suffix=${{ matrix.variant != '' && format('-{0}', matrix.variant) || '' }}
type=sha,prefix=${{ matrix.variant != '' && format('{0}-', matrix.variant) || 'sha-' }}
type=raw,value=${{ matrix.variant }},enable=${{ matrix.variant != '' }}
type=raw,value=latest,enable=${{ matrix.variant == '' }}
- name: Build and push
id: push
uses: docker/build-push-action@v7
- name: Build and push variant (bake)
id: bake
uses: docker/bake-action@v7
with:
context: .
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: true
sbom: true
- name: Attest build provenance
uses: actions/attest-build-provenance@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
files: |
./docker-bake.hcl
cwd://${{ steps.meta.outputs.bake-file-tags }}
cwd://${{ steps.meta.outputs.bake-file-labels }}
targets: ${{ matrix.bake_target }}
push: true
set: |
*.cache-from=type=gha
*.cache-to=type=gha,mode=max

View file

@ -1,5 +1,8 @@
ARG PYTHON_VERSION=3.11
ARG DISTROLESS_IMAGE=gcr.io/distroless/python3-debian13
# ---- Build stage: compile native extensions, build wheel ----
FROM python:3.11-slim AS builder
FROM python:${PYTHON_VERSION}-slim AS builder
RUN apt-get update && \
apt-get install -y --no-install-recommends \
@ -13,34 +16,41 @@ WORKDIR /build
# Layer 1: install deps only (cached unless pyproject.toml/uv.lock change)
COPY pyproject.toml uv.lock README.md ./
# Stub package so uv can resolve the local ".[proxy]" without full source
# Stub package so uv can resolve the local extras without full source
RUN mkdir -p headroom && touch headroom/__init__.py
ARG HEADROOM_EXTRAS=proxy,code
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system ".[proxy]"
uv pip install --system ".[${HEADROOM_EXTRAS}]"
# Layer 2: copy real source, reinstall only headroom-ai (no deps)
COPY headroom/ headroom/
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --system --no-deps --reinstall-package headroom-ai .
# ---- Runtime stage: minimal image with only what's needed ----
FROM python:3.11-slim AS runtime
# ---- Runtime stage (python-slim): supports root/nonroot via build arg ----
FROM python:${PYTHON_VERSION}-slim AS runtime-slim-base
ARG RUNTIME_USER=nonroot
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
RUN groupadd --gid 1000 headroom && \
useradd --uid 1000 --gid headroom --create-home headroom
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin/headroom /usr/local/bin/headroom
RUN mkdir -p /data /home/headroom/.headroom && \
chown -R headroom:headroom /data /home/headroom/.headroom
RUN mkdir -p /home/nonroot /data && \
if [ "$RUNTIME_USER" = "nonroot" ]; then \
groupadd --gid 1000 nonroot && \
useradd --uid 1000 --gid nonroot --create-home nonroot && \
mkdir -p /home/nonroot/.headroom && \
chown -R nonroot:nonroot /data /home/nonroot; \
else \
mkdir -p /root/.headroom; \
fi
USER headroom
WORKDIR /home/headroom
USER ${RUNTIME_USER}
WORKDIR /home/nonroot
ENV HEADROOM_HOST=0.0.0.0 \
PYTHONUNBUFFERED=1 \
@ -50,3 +60,25 @@ EXPOSE 8787
ENTRYPOINT ["headroom", "proxy"]
CMD ["--host", "0.0.0.0", "--port", "8787"]
FROM ${DISTROLESS_IMAGE} AS runtime-slim
ARG RUNTIME_USER=nonroot
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
USER ${RUNTIME_USER}
WORKDIR /app
ENV HEADROOM_HOST=0.0.0.0 \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=/usr/local/lib/python3.11/site-packages
EXPOSE 8787
ENTRYPOINT ["python3", "-m", "headroom.cli", "proxy"]
CMD ["--host", "0.0.0.0", "--port", "8787"]
# Default published image remains python-slim runtime
FROM runtime-slim-base AS runtime

View file

@ -420,6 +420,40 @@ pip install "headroom-ai[langchain]" # LangChain (experimental)
pip install "headroom-ai[evals]" # Evaluation framework only
```
### Container images (GHCR tags)
- supported platforms: `linux/amd64`, `linux/arm64`
- tags `:code` - image with Code-Aware Compression (AST-based) i.e. `pip install "headroom-ai[proxy,code]"`
- tags `:slim` - image with distorless base
| Tag | | Extras | Docker Bake target |
|---------------------|------------------------------------------------------|--------------|-----------------------------|
| `<version>` | ```ghcr.io/chopratejas/headroom:<version>``` | `proxy` | `runtime` |
| `latest` | ```ghcr.io/chopratejas/headroom:latest``` | `proxy` | `runtime` |
| `nonroot` | ```ghcr.io/chopratejas/headroom:nonroot``` | `proxy` | `runtime-nonroot` |
| `code` | ```ghcr.io/chopratejas/headroom:code``` | `proxy,code` | `runtime-code` |
| `code-nonroot` | ```ghcr.io/chopratejas/headroom:code-nonroot``` | `proxy,code` | `runtime-code-nonroot` |
| `slim` | ```ghcr.io/chopratejas/headroom:slim``` | `proxy` | `runtime-slim` |
| `slim-nonroot` | ```ghcr.io/chopratejas/headroom:slim-nonroot``` | `proxy` | `runtime-slim-nonroot` |
| `code-slim` | ```ghcr.io/chopratejas/headroom:code-slim``` | `proxy,code` | `runtime-code-slim` |
| `code-slim-nonroot` | ```ghcr.io/chopratejas/headroom:code-slim-nonroot``` | `proxy,code` | `runtime-code-slim-nonroot` |
### Docker Bake
```bash
# List all available build targets
docker buildx bake --list targets
# Build default image locally (proxy + nonroot)
docker buildx bake runtime-default
# Build one variant and load to local Docker image store
docker buildx bake runtime-code-slim-nonroot \
--set runtime-code-slim-nonroot.platform=linux/amd64 \
--set runtime-code-slim-nonroot.tags=headroom:local \
--load
```
Python 3.10+
---

88
docker-bake.hcl Normal file
View file

@ -0,0 +1,88 @@
target "docker-metadata-action" {}
target "_common" {
context = "."
dockerfile = "Dockerfile"
platforms = ["linux/amd64", "linux/arm64"]
}
target "runtime-default" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime"
args = {
HEADROOM_EXTRAS = "proxy"
RUNTIME_USER = "nonroot"
}
}
target "runtime" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime"
args = {
HEADROOM_EXTRAS = "proxy"
RUNTIME_USER = "root"
}
}
target "runtime-nonroot" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime"
args = {
HEADROOM_EXTRAS = "proxy"
RUNTIME_USER = "nonroot"
}
}
target "runtime-code" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime"
args = {
HEADROOM_EXTRAS = "proxy,code"
RUNTIME_USER = "root"
}
}
target "runtime-code-nonroot" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime"
args = {
HEADROOM_EXTRAS = "proxy,code"
RUNTIME_USER = "nonroot"
}
}
target "runtime-slim" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime-slim"
args = {
HEADROOM_EXTRAS = "proxy"
RUNTIME_USER = "root"
}
}
target "runtime-slim-nonroot" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime-slim"
args = {
HEADROOM_EXTRAS = "proxy"
RUNTIME_USER = "nonroot"
}
}
target "runtime-code-slim" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime-slim"
args = {
HEADROOM_EXTRAS = "proxy,code"
RUNTIME_USER = "root"
}
}
target "runtime-code-slim-nonroot" {
inherits = ["_common", "docker-metadata-action"]
target = "runtime-slim"
args = {
HEADROOM_EXTRAS = "proxy,code"
RUNTIME_USER = "nonroot"
}
}