chopratejas commited on
Commit
51faf9b
·
2 Parent(s): d0998bbe36d11c

Merge pull request #91 from pratikbin/main

Browse files
Files changed (3) hide show
  1. .dockerignore +43 -1
  2. .github/workflows/docker.yml +67 -0
  3. Dockerfile +51 -7
.dockerignore CHANGED
@@ -1,15 +1,57 @@
 
1
  .git
 
 
 
 
2
  __pycache__
3
  *.pyc
4
  *.pyo
 
 
 
 
 
5
  .pytest_cache
6
  .coverage
7
  .mypy_cache
8
  .ruff_cache
 
 
 
 
 
9
  tests/
10
  docs/
 
11
  CHANGELOG.md
12
  LICENSE
13
  NOTICE
 
 
 
 
 
 
 
 
 
14
  .env
15
- *.log
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # VCS
2
  .git
3
+ .github
4
+ .gitignore
5
+
6
+ # Python artifacts
7
  __pycache__
8
  *.pyc
9
  *.pyo
10
+ *.egg-info
11
+ dist/
12
+ build/
13
+
14
+ # Dev/test tooling
15
  .pytest_cache
16
  .coverage
17
  .mypy_cache
18
  .ruff_cache
19
+ .pre-commit-config.yaml
20
+ .venv
21
+ venv
22
+
23
+ # Tests & docs (not needed in image)
24
  tests/
25
  docs/
26
+ mkdocs.yml
27
  CHANGELOG.md
28
  LICENSE
29
  NOTICE
30
+
31
+ # JS/TS artifacts (dashboard, SDK — not part of proxy image)
32
+ apps/
33
+ sdk/
34
+ plugins/
35
+ node_modules/
36
+ *.tgz
37
+
38
+ # Secrets & local config
39
  .env
40
+ .env.*
41
+ *.log
42
+
43
+ # IDE
44
+ .vscode
45
+ .idea
46
+ *.swp
47
+
48
+ # Docker
49
+ Dockerfile
50
+ docker-compose*.yml
51
+ .dockerignore
52
+
53
+ # Misc
54
+ .pi-lens/
55
+ .superpowers/
56
+ examples/
57
+ node-compile-cache/
.github/workflows/docker.yml ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Docker
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ release:
6
+ types: [published]
7
+
8
+ env:
9
+ REGISTRY: ghcr.io
10
+ IMAGE_NAME: ${{ github.repository }}
11
+
12
+ permissions:
13
+ contents: read
14
+ packages: write
15
+ attestations: write
16
+ id-token: write
17
+
18
+ jobs:
19
+ docker:
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v6
23
+
24
+ - name: Set up QEMU
25
+ uses: docker/setup-qemu-action@v4
26
+
27
+ - name: Set up Docker Buildx
28
+ uses: docker/setup-buildx-action@v4
29
+
30
+ - name: Log in to GHCR
31
+ uses: docker/login-action@v4
32
+ with:
33
+ registry: ${{ env.REGISTRY }}
34
+ username: ${{ github.actor }}
35
+ password: ${{ secrets.GITHUB_TOKEN }}
36
+
37
+ - name: Extract metadata
38
+ id: meta
39
+ uses: docker/metadata-action@v6
40
+ with:
41
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
42
+ tags: |
43
+ type=ref,event=branch
44
+ type=ref,event=pr
45
+ type=semver,pattern={{version}}
46
+ type=semver,pattern={{major}}.{{minor}}
47
+ type=sha,prefix=sha-
48
+
49
+ - name: Build and push
50
+ id: push
51
+ uses: docker/build-push-action@v7
52
+ with:
53
+ context: .
54
+ platforms: linux/amd64,linux/arm64
55
+ tags: ${{ steps.meta.outputs.tags }}
56
+ labels: ${{ steps.meta.outputs.labels }}
57
+ cache-from: type=gha
58
+ cache-to: type=gha,mode=max
59
+ provenance: true
60
+ sbom: true
61
+
62
+ - name: Attest build provenance
63
+ uses: actions/attest-build-provenance@v4
64
+ with:
65
+ subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
66
+ subject-digest: ${{ steps.push.outputs.digest }}
67
+ push-to-registry: true
Dockerfile CHANGED
@@ -1,8 +1,52 @@
1
- FROM python:3.11-slim
2
- RUN apt-get update && apt-get install -y --no-install-recommends curl build-essential g++ && rm -rf /var/lib/apt/lists/*
3
- COPY . /app
4
- WORKDIR /app
5
- RUN pip install -e .[proxy]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  EXPOSE 8787
7
- HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD curl -f http://localhost:8787/health || exit 1
8
- ENTRYPOINT ["headroom", "proxy"]
 
 
1
+ # ---- Build stage: compile native extensions, build wheel ----
2
+ FROM python:3.11-slim AS builder
3
+
4
+ RUN apt-get update && \
5
+ apt-get install -y --no-install-recommends \
6
+ build-essential \
7
+ g++ \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
+ COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
11
+
12
+ WORKDIR /build
13
+
14
+ # Layer 1: install deps only (cached unless pyproject.toml/uv.lock change)
15
+ COPY pyproject.toml uv.lock README.md ./
16
+ # Stub package so uv can resolve the local ".[proxy]" without full source
17
+ RUN mkdir -p headroom && touch headroom/__init__.py
18
+ RUN --mount=type=cache,target=/root/.cache/uv \
19
+ uv pip install --system ".[proxy]"
20
+
21
+ # Layer 2: copy real source, reinstall only headroom-ai (no deps)
22
+ COPY headroom/ headroom/
23
+ RUN --mount=type=cache,target=/root/.cache/uv \
24
+ uv pip install --system --no-deps --reinstall-package headroom-ai .
25
+
26
+ # ---- Runtime stage: minimal image with only what's needed ----
27
+ FROM python:3.11-slim AS runtime
28
+
29
+ RUN apt-get update && \
30
+ apt-get install -y --no-install-recommends curl && \
31
+ rm -rf /var/lib/apt/lists/*
32
+
33
+ RUN groupadd --gid 1000 headroom && \
34
+ useradd --uid 1000 --gid headroom --create-home headroom
35
+
36
+ COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
37
+ COPY --from=builder /usr/local/bin/headroom /usr/local/bin/headroom
38
+
39
+ RUN mkdir -p /data /home/headroom/.headroom && \
40
+ chown -R headroom:headroom /data /home/headroom/.headroom
41
+
42
+ USER headroom
43
+ WORKDIR /home/headroom
44
+
45
+ ENV HEADROOM_HOST=0.0.0.0 \
46
+ PYTHONUNBUFFERED=1 \
47
+ PYTHONDONTWRITEBYTECODE=1
48
+
49
  EXPOSE 8787
50
+
51
+ ENTRYPOINT ["headroom", "proxy"]
52
+ CMD ["--host", "0.0.0.0", "--port", "8787"]