From e518c669e42d049961b104d49d6c7eb9ef72bacb Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 30 Jun 2026 19:34:06 +0800 Subject: [PATCH] chore(docker): enable files_mcp service in container image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile: COPY files_mcp package, mkdir -p /app/data/files at build time, set ENV FILES_MCP_ROOT=/app/data/files as the default sandbox root (overridable at runtime). - docker-compose.yml: surface FILES_MCP_ROOT in the env block with the same default, so operators can override it via .env or -e. FILES_MCP_ROOT must exist at process start (path_guard._init_root checks is_dir()), so the directory is created during build rather than deferred to entrypoint — fail-fast at image build beats a runtime RuntimeError on every container start. Default lives under /app/data so it rides the existing data volume (./data:/app/data) and persists across container restarts alongside connections.json / pending_jobs.json / logs/. Verified locally: docker compose config --quiet passes; FILES_MCP_ROOT resolves to /app/data/files in the rendered config. Full image build not run (docker daemon unavailable in this environment); please run `docker compose up -d --build` to confirm in your environment. Co-Authored-By: Claude Fable 5 --- Dockerfile | 10 ++++++++++ docker-compose.yml | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/Dockerfile b/Dockerfile index bb522fd..aa10f42 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,10 +59,20 @@ RUN uv sync --index-url=https://pypi.tuna.tsinghua.edu.cn/simple/ --frozen --no- # Now copy the source and let uv wire it in. COPY main.py ./ COPY spark_executor ./spark_executor +COPY files_mcp ./files_mcp COPY common ./common COPY gunicorn.conf.py ./ RUN uv sync --index-url=https://pypi.tuna.tsinghua.edu.cn/simple/ --frozen --no-dev +# --- files_mcp sandbox --- +# FILES_MCP_ROOT is the only directory the files_mcp tools can touch. It +# must exist at process start (path_guard._init_root checks is_dir()) and +# persist across container restarts, so it lives under the data volume. +# Operators can override FILES_MCP_ROOT at `docker run` / compose to point +# at a separate host mount if they want strict isolation from /app/data. +RUN mkdir -p /app/data/files +ENV FILES_MCP_ROOT=/app/data/files + # Put the venv on PATH so `python` / `gunicorn` / `uvicorn` resolve to the project env. ENV PATH=/app/.venv/bin:$PATH ENV PYTHONUNBUFFERED=1 diff --git a/docker-compose.yml b/docker-compose.yml index da306f4..6387c75 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,6 +56,13 @@ services: # 'spark2-submit' on mixed-version hosts, or to a wrapper path. SPARK_EXECUTOR_SPARK_SUBMIT_BIN: ${SPARK_EXECUTOR_SPARK_SUBMIT_BIN:-spark-submit} + # --- files_mcp sandbox --- + # The only directory the files_mcp tools can read or write. Lives + # under the data volume so it persists across restarts. Override + # at deploy time to mount a separate host directory for stricter + # isolation from connections / pending_jobs / logs. + FILES_MCP_ROOT: ${FILES_MCP_ROOT:-/app/data/files} + # --- Runtime paths (consumed by docker-entrypoint.sh, not common/config.py) --- # Override to point at a different JDK install or pre-mounted Spark # distribution. The entrypoint re-derives PATH from these at every