SEUyishu commited on
Commit
4dcbc64
·
verified ·
1 Parent(s): adc673d

Upload 2 files

Browse files
Files changed (2) hide show
  1. Dockerfile +52 -61
  2. entrypoint.py +56 -0
Dockerfile CHANGED
@@ -1,61 +1,52 @@
1
- # M3GNet FastMCP HuggingFace Space image
2
- FROM python:3.10-slim
3
-
4
- ENV PIP_NO_CACHE_DIR=1 \
5
- HF_HUB_DISABLE_TELEMETRY=1 \
6
- TF_CPP_MIN_LOG_LEVEL=2 \
7
- CUDA_VISIBLE_DEVICES=-1
8
-
9
- WORKDIR /app
10
-
11
- # System build/runtime dependencies for pymatgen, ASE, and TensorFlow
12
- RUN apt-get update \
13
- && apt-get install -y --no-install-recommends \
14
- build-essential \
15
- git \
16
- curl \
17
- libopenblas-dev \
18
- liblapack-dev \
19
- libffi-dev \
20
- libssl-dev \
21
- ca-certificates \
22
- && rm -rf /var/lib/apt/lists/*
23
-
24
- # Copy everything from the build context into the image
25
- COPY . /app
26
-
27
- # Install the core M3GNet library. The logic below works for both
28
- # "full repository" contexts (with setup.py at root) and the case where
29
- # the repo lives in a nested m3gnet/ directory. If neither is present we
30
- # fall back to installing the published package from PyPI.
31
- RUN set -ex \
32
- && pip install --upgrade pip \
33
- && if [ -f "setup.py" ] || [ -f "pyproject.toml" ]; then \
34
- if [ -f "requirements.txt" ]; then pip install --no-cache-dir -r requirements.txt; fi && \
35
- pip install --no-cache-dir .; \
36
- elif [ -f "m3gnet/setup.py" ] || [ -f "m3gnet/pyproject.toml" ]; then \
37
- if [ -f "m3gnet/requirements.txt" ]; then pip install --no-cache-dir -r m3gnet/requirements.txt; fi && \
38
- pip install --no-cache-dir ./m3gnet; \
39
- else \
40
- pip install --no-cache-dir m3gnet==0.2.4; \
41
- fi
42
-
43
- # Install MCP service dependencies
44
- RUN if [ -f "mcp_output/requirements.txt" ]; then \
45
- pip install --no-cache-dir -r mcp_output/requirements.txt; \
46
- elif [ -f "requirements.txt" ]; then \
47
- pip install --no-cache-dir -r requirements.txt; \
48
- fi
49
-
50
- EXPOSE 7860
51
-
52
- CMD ["/bin/sh", "-c", "\
53
- ENTRY=\$(find /app -maxdepth 3 -name start_mcp.py | head -n 1); \
54
- if [ -n \"$ENTRY\" ]; then \
55
- echo 'Launching MCP service using' $ENTRY; \
56
- python $ENTRY --mode sse --host 0.0.0.0 --port 7860; \
57
- else \
58
- echo 'start_mcp.py not found. Directory tree:'; \
59
- find /app -maxdepth 3 -type f; \
60
- exit 1; \
61
- fi"]
 
1
+ # M3GNet FastMCP HuggingFace Space image
2
+ FROM python:3.10-slim
3
+
4
+ ENV PIP_NO_CACHE_DIR=1 \
5
+ HF_HUB_DISABLE_TELEMETRY=1 \
6
+ TF_CPP_MIN_LOG_LEVEL=2 \
7
+ CUDA_VISIBLE_DEVICES=-1
8
+
9
+ WORKDIR /app
10
+
11
+ # System build/runtime dependencies for pymatgen, ASE, and TensorFlow
12
+ RUN apt-get update \
13
+ && apt-get install -y --no-install-recommends \
14
+ build-essential \
15
+ git \
16
+ curl \
17
+ libopenblas-dev \
18
+ liblapack-dev \
19
+ libffi-dev \
20
+ libssl-dev \
21
+ ca-certificates \
22
+ && rm -rf /var/lib/apt/lists/*
23
+
24
+ # Copy everything from the build context into the image
25
+ COPY . /app
26
+
27
+ # Install the core M3GNet library. The logic below works for both
28
+ # "full repository" contexts (with setup.py at root) and the case where
29
+ # the repo lives in a nested m3gnet/ directory. If neither is present we
30
+ # fall back to installing the published package from PyPI.
31
+ RUN set -ex \
32
+ && pip install --upgrade pip \
33
+ && if [ -f "setup.py" ] || [ -f "pyproject.toml" ]; then \
34
+ if [ -f "requirements.txt" ]; then pip install --no-cache-dir -r requirements.txt; fi && \
35
+ pip install --no-cache-dir .; \
36
+ elif [ -f "m3gnet/setup.py" ] || [ -f "m3gnet/pyproject.toml" ]; then \
37
+ if [ -f "m3gnet/requirements.txt" ]; then pip install --no-cache-dir -r m3gnet/requirements.txt; fi && \
38
+ pip install --no-cache-dir ./m3gnet; \
39
+ else \
40
+ pip install --no-cache-dir m3gnet==0.2.4; \
41
+ fi
42
+
43
+ # Install MCP service dependencies
44
+ RUN if [ -f "mcp_output/requirements.txt" ]; then \
45
+ pip install --no-cache-dir -r mcp_output/requirements.txt; \
46
+ elif [ -f "requirements.txt" ]; then \
47
+ pip install --no-cache-dir -r requirements.txt; \
48
+ fi
49
+
50
+ EXPOSE 7860
51
+
52
+ CMD ["python", "/app/entrypoint.py"]
 
 
 
 
 
 
 
 
 
entrypoint.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Container entrypoint for the M3GNet FastMCP service.
2
+
3
+ The script searches for ``start_mcp.py`` in the extracted project tree and
4
+ executes it with sensible defaults. This avoids hard-coding the deployment
5
+ layout, which is helpful when only the ``mcp_output`` folder is uploaded to a
6
+ Service (e.g., HuggingFace Space).
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ import sys
13
+ from pathlib import Path
14
+
15
+
16
+ def find_start_script(root: Path) -> Path | None:
17
+ """Return the first ``start_mcp.py`` found within ``root`` (depth <= 3)."""
18
+
19
+ max_depth = 3
20
+ queue = [(root, 0)]
21
+ while queue:
22
+ current, depth = queue.pop(0)
23
+ if not current.is_dir():
24
+ continue
25
+ # Look for the script in the current directory first
26
+ candidate = current / "start_mcp.py"
27
+ if candidate.is_file():
28
+ return candidate
29
+ if depth >= max_depth:
30
+ continue
31
+ for child in current.iterdir():
32
+ if child.is_dir():
33
+ queue.append((child, depth + 1))
34
+ return None
35
+
36
+
37
+ def main() -> None:
38
+ root = Path("/app")
39
+ script = find_start_script(root)
40
+ if script is None:
41
+ print("[ERROR] 未找到 start_mcp.py。/app 目录内容如下:", file=sys.stderr)
42
+ for path in root.rglob("*"):
43
+ if path.is_file():
44
+ print(f" - {path.relative_to(root)}", file=sys.stderr)
45
+ sys.exit(1)
46
+
47
+ host = os.environ.get("MCP_HOST", "0.0.0.0")
48
+ port = os.environ.get("MCP_PORT", "7860")
49
+ mode = os.environ.get("MCP_MODE", "sse")
50
+
51
+ print(f"[INFO] 启动 FastMCP 服务:{script} (mode={mode}, host={host}, port={port})")
52
+ os.execv(sys.executable, [sys.executable, str(script), "--mode", mode, "--host", host, "--port", port])
53
+
54
+
55
+ if __name__ == "__main__":
56
+ main()