Some checks failed
Invert the agent model: the agent IS the computer. The message pump becomes the kernel, handlers are sandboxed apps, and all access is mediated by the platform. Phase 1 — Container foundation: - Multi-stage Dockerfile (python:3.12-slim, non-root user, /data volume) - deploy/entrypoint.py with --dry-run config validation - docker-compose.yml (cap_drop ALL, read_only, no-new-privileges) - docker-compose.dev.yml overlay for development - CI Docker build smoke test Phase 2 — Security hardening: - xml_pipeline/security/ module with default-deny container mode - Permission gate: per-listener tool allowlist enforcement - Network policy: egress control (only declared LLM backend domains) - Shell tool: disabled in container mode - File tool: restricted to /data and /config in container mode - Fetch tool: integrates network egress policy - Config loader: parses security and network YAML sections Phase 3 — Management plane: - Agent app (port 8080): minimal /health, /inject, /ws only - Management app (port 9090): full API, audit log, dashboard - SQLite-backed audit log for tool invocations and security events - Static web dashboard (no framework, WebSocket-driven) - CLI --split flag for dual-port serving All 439 existing tests pass with zero regressions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
99 lines
3.1 KiB
Docker
99 lines
3.1 KiB
Docker
# AgentOS — Sealed organism runtime
|
|
#
|
|
# Multi-stage build: python:3.12-slim builder + minimal runtime.
|
|
# Not Alpine: musl breaks lxml C extensions.
|
|
#
|
|
# Usage:
|
|
# docker build -t agentos .
|
|
# docker run -v ./organism.yaml:/config/organism.yaml \
|
|
# -e XAI_API_KEY=xai-... \
|
|
# -p 8080:8080 -p 9090:9090 \
|
|
# agentos
|
|
|
|
# =============================================================================
|
|
# Stage 1: Builder — install dependencies and build wheels
|
|
# =============================================================================
|
|
FROM python:3.12-slim AS builder
|
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
build-essential \
|
|
libxml2-dev \
|
|
libxslt1-dev \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /build
|
|
|
|
# Copy dependency specification first (layer caching)
|
|
COPY pyproject.toml .
|
|
COPY README.md .
|
|
|
|
# Install into a virtual environment for clean copy
|
|
RUN python -m venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
|
|
# Install core + server + all LLM providers
|
|
RUN pip install --no-cache-dir --upgrade pip && \
|
|
pip install --no-cache-dir -e ".[all]"
|
|
|
|
# Copy source code
|
|
COPY xml_pipeline/ xml_pipeline/
|
|
COPY third_party/ third_party/
|
|
COPY handlers/ handlers/
|
|
COPY examples/ examples/
|
|
COPY config/ config/
|
|
COPY deploy/ deploy/
|
|
|
|
# Re-install with source (editable mode needs the source)
|
|
RUN pip install --no-cache-dir -e ".[all]"
|
|
|
|
# =============================================================================
|
|
# Stage 2: Runtime — minimal image with only what's needed
|
|
# =============================================================================
|
|
FROM python:3.12-slim AS runtime
|
|
|
|
# Runtime dependencies for lxml
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
libxml2 \
|
|
libxslt1.1 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create non-root user
|
|
RUN groupadd -r organism && useradd -r -g organism -d /home/organism -s /bin/false organism
|
|
|
|
# Copy virtual environment from builder
|
|
COPY --from=builder /opt/venv /opt/venv
|
|
ENV PATH="/opt/venv/bin:$PATH"
|
|
|
|
# Copy application source
|
|
WORKDIR /app
|
|
COPY --from=builder /build/xml_pipeline/ xml_pipeline/
|
|
COPY --from=builder /build/third_party/ third_party/
|
|
COPY --from=builder /build/handlers/ handlers/
|
|
COPY --from=builder /build/examples/ examples/
|
|
COPY --from=builder /build/config/ config/
|
|
COPY --from=builder /build/deploy/ deploy/
|
|
COPY --from=builder /build/pyproject.toml .
|
|
COPY --from=builder /build/README.md .
|
|
|
|
# Create writable data directory and config mount point
|
|
RUN mkdir -p /data /config && chown -R organism:organism /data /config
|
|
|
|
# Dashboard static files
|
|
COPY dashboard/ /app/dashboard/
|
|
|
|
# Volume for persistent data
|
|
VOLUME ["/data"]
|
|
|
|
# Expose agent bus (8080) and management plane (9090)
|
|
EXPOSE 8080 9090
|
|
|
|
# Switch to non-root user
|
|
USER organism
|
|
|
|
# Health check against agent port
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')" || exit 1
|
|
|
|
# Default: boot the organism via entrypoint
|
|
ENTRYPOINT ["python", "-m", "deploy.entrypoint"]
|
|
CMD ["/config/organism.yaml"]
|