Dockerfile
Rama main · réplica de lectura del repositorio original.
## ── Builder stage ────────────────────────────────────────────────────────────
FROM python:3.14.8-alpine3.23@sha256:e7cff362a12454395f8dc99607c21a602ea880cdce03538877b90c2ba932b16f AS builder
WORKDIR /app
# CPython 3.14.8 predates the upstream tarfile filter-rejection repair.
# Verify the complete upstream source before and after this bounded overlay.
COPY deploy/docker/vendor/cpython-3.14.8/apply_tarfile_fix.py /tmp/apply_tarfile_fix.py
RUN python /tmp/apply_tarfile_fix.py && rm /tmp/apply_tarfile_fix.py
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ARG SSL_CERT_FILE
ARG REQUESTS_CA_BUNDLE
ARG CURL_CA_BUNDLE
ARG PIP_CERT
ENV HTTP_PROXY=${HTTP_PROXY} \
HTTPS_PROXY=${HTTPS_PROXY} \
NO_PROXY=${NO_PROXY} \
SSL_CERT_FILE=${SSL_CERT_FILE} \
REQUESTS_CA_BUNDLE=${REQUESTS_CA_BUNDLE} \
CURL_CA_BUNDLE=${CURL_CA_BUNDLE} \
PIP_CERT=${PIP_CERT}
# Build-time deps for wheel compilation when musllinux wheels are unavailable.
# Pins track the base-image digest above; refresh both together.
RUN apk add --no-cache build-base~=0.5 ca-certificates~=20260909 git~=2.52 libffi-dev~=3.5 linux-headers~=6.16 \
&& apk upgrade --no-cache --available \
&& update-ca-certificates
COPY --from=ghcr.io/astral-sh/uv:0.13.5@sha256:32a7bb39b496babbd997b0a39a4d66c126bdaf5661b302bf6f06abda8deca6ff /uv /uvx /bin/
COPY pyproject.toml uv.lock README.md LICENSE ./
COPY docs/registry/PYPI_README.md ./docs/registry/
COPY src/ ./src/
COPY deploy/supabase/postgres/ ./deploy/supabase/postgres/
COPY deploy/docker/runtime-security-requirements.txt ./deploy/docker/runtime-security-requirements.txt
COPY deploy/docker/tornado-security-requirements.txt ./deploy/docker/tornado-security-requirements.txt
# tree-sitter-typescript 0.23.2 has no musllinux aarch64 wheel and its PyPI
# sdist omits internal headers needed to compile the bundled grammars.
# Keep the exact upstream v0.23.2 headers in the build context so Python 3.14
# arm64 builds do not depend on an incomplete sdist. See the adjacent README
# and license for provenance and the pinned source digests.
COPY deploy/docker/vendor/tree-sitter-typescript-0.23.2/tree_sitter/parser.h \
/usr/local/include/tree_sitter/parser.h
COPY deploy/docker/vendor/tree-sitter-typescript-0.23.2/common/scanner.h \
/usr/local/include/tree-sitter-typescript/common/scanner.h
# Extras baked into the published control-plane image. Cloud SDKs (aws/azure/gcp)
# ship by default so self-hosted BYOC (connect an AWS/Azure/GCP account read-only,
# incl. IRSA/workload-identity) works out of the box (#3832). Override at build
# time for a lean image, e.g. --build-arg AGENT_BOM_EXTRAS=api,snowflake,postgres.
ARG AGENT_BOM_EXTRAS=api,snowflake,postgres,aws,azure,gcp
RUN set -eu; \
test "$(sha256sum /usr/local/include/tree_sitter/parser.h | cut -d ' ' -f 1)" = \
"a1f6ef161fbaf48a0e10fca90ef5290a062462b307b3898aa562993853b9f80a"; \
test "$(sha256sum /usr/local/include/tree-sitter-typescript/common/scanner.h | cut -d ' ' -f 1)" = \
"da66ef2bd14a3f7ea743e25ba068c6c9aae2c3509db200ff80c4a0e6116e564c"; \
mkdir -p /usr/local/include/tree-sitter-typescript/tsx/src; \
sync_args=""; \
for extra in $(printf '%s' "${AGENT_BOM_EXTRAS}" | tr ',' ' '); do \
case "${extra}" in *[!a-zA-Z0-9_-]*|'') exit 2 ;; esac; \
sync_args="${sync_args} --extra ${extra}"; \
done; \
CFLAGS="-I/usr/local/include/tree-sitter-typescript/tsx/src" \
uv sync --locked --no-dev --no-editable ${sync_args}; \
uv pip install --no-cache --no-config --python /app/.venv/bin/python --no-deps --require-hashes \
-r deploy/docker/runtime-security-requirements.txt; \
if /app/.venv/bin/python -c "import importlib.util, sys; sys.exit(importlib.util.find_spec('tornado') is None)"; then \
uv pip install --no-cache --no-config --python /app/.venv/bin/python --no-deps --require-hashes \
--only-binary=:all: -r deploy/docker/tornado-security-requirements.txt; \
fi
## ── Runtime stage ────────────────────────────────────────────────────────────
FROM python:3.14.8-alpine3.23@sha256:e7cff362a12454395f8dc99607c21a602ea880cdce03538877b90c2ba932b16f
ARG VERSION=0.114.0
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ARG SSL_CERT_FILE
ARG REQUESTS_CA_BUNDLE
ARG CURL_CA_BUNDLE
ARG PIP_CERT
LABEL maintainer="W S <34316639+msaad00@users.noreply.github.com>"
LABEL description="AI supply-chain BOM: every agent, MCP server and AI package, and what each one can reach."
LABEL org.opencontainers.image.version="${VERSION}"
LABEL org.opencontainers.image.source="https://github.com/koda-ai-studio/agent-bom"
LABEL org.opencontainers.image.licenses="Apache-2.0"
# Copy the frozen environment from the identical Python base image. Keeping
# the same absolute path preserves console-script shebangs generated by uv.
COPY --from=builder /app/.venv /app/.venv
COPY --from=builder /usr/local/lib/python3.14/tarfile.py /usr/local/lib/python3.14/tarfile.py
COPY --from=builder /app/LICENSE /app/LICENSE
COPY --from=builder /app/deploy/supabase/postgres /opt/agent-bom/deploy/supabase/postgres
# Repository URL scans shallow-clone with git at runtime as the non-root user.
RUN apk add --no-cache ca-certificates~=20260909 git~=2.52 libffi~=3.5 libgcc~=15.2 libstdc++~=15.2 \
&& apk upgrade --no-cache --available \
&& update-ca-certificates
# The runtime never installs packages. Remove packaging tools and pip's vendored
# dependency tree so scanner-visible build utilities cannot become runtime CVEs.
RUN python -m pip uninstall --yes setuptools wheel pip \
&& rm -rf /root/.cache/pip
# Create non-root user for least-privilege execution
RUN addgroup -S abom && adduser -S -G abom abom
WORKDIR /workspace
RUN chown abom:abom /workspace
# Pre-create the state dir and hand ownership to abom (uid/gid of the abom
# user) so a named volume or bind mount at /home/abom/.agent-bom is writable.
# Without this the mount lands root-owned and abom (non-root) cannot create
# jobs.db / vulns.db, crash-looping the API.
RUN mkdir -p /home/abom/.agent-bom && chown -R abom:abom /home/abom
USER abom
ENV PYTHONUNBUFFERED=1
ENV TERM=xterm-256color
ENV VIRTUAL_ENV=/app/.venv
ENV PATH="/app/.venv/bin:${PATH}"
ENV HTTP_PROXY=${HTTP_PROXY}
ENV HTTPS_PROXY=${HTTPS_PROXY}
ENV NO_PROXY=${NO_PROXY}
ENV SSL_CERT_FILE=${SSL_CERT_FILE}
ENV REQUESTS_CA_BUNDLE=${REQUESTS_CA_BUNDLE}
ENV CURL_CA_BUNDLE=${CURL_CA_BUNDLE}
ENV PIP_CERT=${PIP_CERT}
# This is a generic CLI image whose default command exits. Long-lived API,
# gateway, proxy, and MCP deployments define process-aware probes in their
# Compose, Helm, or dedicated runtime-image contracts.
HEALTHCHECK NONE
ENTRYPOINT ["agent-bom"]
CMD ["--help"]