# syntax=docker/dockerfile:1 # Build context: ./backend FROM docker.io/library/python:3.12-slim AS build COPY --from=ghcr.io/astral-sh/uv:0.5 /uv /bin/uv ENV UV_LINK_MODE=copy WORKDIR /app # Install into a self-contained venv. No uv.lock in the repo, so resolve from # pyproject.toml directly. src/ is needed at build time because the hatchling # build reads src/oc8. COPY pyproject.toml ./ COPY src ./src RUN uv venv /opt/venv && VIRTUAL_ENV=/opt/venv uv pip install . FROM docker.io/library/python:3.12-slim AS runtime # libpq/build tools are not needed: asyncpg and psycopg[binary] ship wheels, # cryptography ships manylinux wheels. If a future dep is source-only on this # platform, add `RUN apt-get update && apt-get install -y --no-install-recommends gcc` # to the build stage. COPY --from=build /opt/venv /opt/venv # Tool-pack plugins may declare Python MCP bridges launched via ``uvx``. # Keeping the generic runner in the image avoids requiring operators to shell # into OC8; a declared package is fetched only when its connection is tested. COPY --from=ghcr.io/astral-sh/uv:0.5 /uv /usr/local/bin/uv RUN ln -s /usr/local/bin/uv /usr/local/bin/uvx # node/npx, for tool-pack plugins whose MCP bridge is only published as an npm # package (hubspot_mcp's official `@hubspot/mcp-server`). Copied from the # official Node image rather than apt-get, matching the uv binary above -- and # pinned to -bookworm-slim explicitly (not the floating `slim` tag) so its # glibc matches this image's own Debian base regardless of which release # `python:3.12-slim` currently resolves to. COPY --from=docker.io/library/node:22-bookworm-slim /usr/local/bin/node /usr/local/bin/node COPY --from=docker.io/library/node:22-bookworm-slim /usr/local/lib/node_modules /usr/local/lib/node_modules RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \ ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx # github_mcp's bridge: GitHub's own official binary, vendored the same way -- # the upstream image's final stage is `gcr.io/distroless/base-debian12` with # nothing but this one binary at /server/github-mcp-server (verified against # github/github-mcp-server's own Dockerfile). Pinned, never `:latest`. COPY --from=ghcr.io/github/github-mcp-server:v1.9.0 /server/github-mcp-server /usr/local/bin/github-mcp-server WORKDIR /app # alembic needs alembic.ini + migrations/ next to it; oc8 itself is installed # into the venv, so src/ is not copied into the runtime. COPY alembic.ini ./ COPY migrations ./migrations ENV PATH="/opt/venv/bin:$PATH" EXPOSE 8099 CMD ["uvicorn", "oc8.main:create_app", "--factory", "--host", "0.0.0.0", "--port", "8099"]