Miyu Horiuchi Claude Opus 4.7 (1M context) commited on
Commit
317d0fc
Β·
1 Parent(s): 796c5f4

HF Spaces: Dockerfile for v2 (FastAPI + React) deployment

Browse files

Two-stage build:
1. node:20-slim β€” npm ci + vite build β†’ web/dist
2. python:3.11-slim β€” install backend deps, copy models/data/built-frontend,
run uvicorn on port 7860 as non-root user (uid 1000,
which HF Spaces requires)

README.md frontmatter switched from sdk:streamlit β†’ sdk:docker, app_port:7860.
HF will detect the Dockerfile and build the v2 stack instead of the legacy
Streamlit app.

.dockerignore keeps the build context small β€” excludes the .venv, node_modules,
training-only parquets (features.parquet, embeddings.parquet etc.), and dev
caches. Final image only contains:
- api/main.py
- src/microbe_model/ + scripts/recommend.py
- models/recommender/ (24 .ubj) + models/phenotype/ (12 files)
- data/media_metadata.parquet + data/media_recipes.parquet
- artifacts/uncultured_predictions.parquet
- web/dist/ (built React app)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files changed (3) hide show
  1. .dockerignore +47 -0
  2. Dockerfile +66 -0
  3. README.md +2 -3
.dockerignore ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .git
2
+ .venv
3
+ .env
4
+ .env.local
5
+ __pycache__
6
+ *.pyc
7
+ *.pyo
8
+ *.pyd
9
+ .pytest_cache
10
+ .ruff_cache
11
+ .mypy_cache
12
+ node_modules
13
+ web/node_modules
14
+ web/dist
15
+ notebooks/scratch
16
+ .ipynb_checkpoints
17
+ .DS_Store
18
+ .vscode
19
+ .idea
20
+ .claude
21
+ .letta
22
+ # Heavy data files we don't ship
23
+ data/genomes
24
+ data/bacdive
25
+ data/features.parquet
26
+ data/training_table.parquet
27
+ data/embeddings.parquet
28
+ data/embeddings.jsonl
29
+ data/uncultured_features.parquet
30
+ data/uncultured_features.jsonl
31
+ data/training_table_v0.parquet
32
+ data/training_table_embeddings.parquet
33
+ data/strain_media.parquet
34
+ data/gtdb_candidates.parquet
35
+ data/bacdive_phenotypes.parquet
36
+ data/features_v0.jsonl
37
+ data/features.jsonl
38
+ data/features_v0.parquet
39
+ data/bac120_metadata.tsv.gz
40
+ artifacts/embeddings.log
41
+ artifacts/featurize.log
42
+ artifacts/phase_c.log
43
+ artifacts/predictions.parquet
44
+ artifacts/predictions_v0.parquet
45
+ artifacts/bacdive_scan.log
46
+ artifacts/mediadive_fetch.log
47
+ docs/
Dockerfile ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1.6
2
+ # Two-stage build:
3
+ # 1. node β€” compile the Vite/React frontend β†’ web/dist
4
+ # 2. python β€” install backend deps, copy models + built frontend, run uvicorn
5
+
6
+ # ─────────────────────────────────────────────────────────────────────
7
+ # Stage 1 β€” build the React frontend
8
+ # ─────────────────────────────────────────────────────────────────────
9
+ FROM node:20-slim AS web-build
10
+ WORKDIR /web
11
+
12
+ COPY web/package.json web/package-lock.json ./
13
+ RUN npm ci --no-audit --no-fund
14
+
15
+ COPY web/ ./
16
+ RUN npm run build
17
+
18
+
19
+ # ─────────────────────────────────────────────────────────────────────
20
+ # Stage 2 β€” Python backend + serve the built frontend
21
+ # ─────────────────────────────────────────────────────────────────────
22
+ FROM python:3.11-slim AS app
23
+
24
+ # System deps for pyrodigal / xgboost wheels
25
+ RUN apt-get update && apt-get install -y --no-install-recommends \
26
+ build-essential \
27
+ curl \
28
+ && rm -rf /var/lib/apt/lists/*
29
+
30
+ # HF Spaces requires the container run as a non-root user (uid 1000)
31
+ RUN useradd -m -u 1000 user
32
+ ENV HOME=/home/user \
33
+ PATH=/home/user/.local/bin:$PATH \
34
+ PYTHONUNBUFFERED=1 \
35
+ PYTHONDONTWRITEBYTECODE=1
36
+
37
+ WORKDIR /app
38
+
39
+ # Install Python deps first (better layer caching)
40
+ COPY requirements.txt ./
41
+ RUN pip install --no-cache-dir --upgrade pip && \
42
+ pip install --no-cache-dir -r requirements.txt
43
+
44
+ # Copy the project (everything needed at runtime)
45
+ COPY --chown=user:user api/ ./api/
46
+ COPY --chown=user:user src/ ./src/
47
+ COPY --chown=user:user scripts/recommend.py ./scripts/recommend.py
48
+ COPY --chown=user:user models/ ./models/
49
+ COPY --chown=user:user artifacts/uncultured_predictions.parquet ./artifacts/uncultured_predictions.parquet
50
+ COPY --chown=user:user data/media_metadata.parquet ./data/media_metadata.parquet
51
+ COPY --chown=user:user data/media_recipes.parquet ./data/media_recipes.parquet
52
+ COPY --chown=user:user pyproject.toml README.md ./
53
+
54
+ # Built frontend from stage 1
55
+ COPY --from=web-build --chown=user:user /web/dist ./web/dist
56
+
57
+ # Make sure microbe_model is importable
58
+ RUN pip install --no-cache-dir -e .
59
+
60
+ # HF Spaces expects 7860; allow override
61
+ ENV PORT=7860
62
+ USER user
63
+
64
+ EXPOSE 7860
65
+
66
+ CMD ["sh", "-c", "uvicorn api.main:app --host 0.0.0.0 --port ${PORT}"]
README.md CHANGED
@@ -3,9 +3,8 @@ title: microbe-model
3
  emoji: 🦠
4
  colorFrom: yellow
5
  colorTo: red
6
- sdk: streamlit
7
- sdk_version: 1.39.0
8
- app_file: app.py
9
  pinned: false
10
  license: mit
11
  short_description: Predict growth conditions and culture media for never-cultured microbes
 
3
  emoji: 🦠
4
  colorFrom: yellow
5
  colorTo: red
6
+ sdk: docker
7
+ app_port: 7860
 
8
  pinned: false
9
  license: mit
10
  short_description: Predict growth conditions and culture media for never-cultured microbes