apoorvrajdev commited on
Commit
ed6ea78
Β·
1 Parent(s): 6a4b2fc

feat(backend): add Dockerfile, .dockerignore, and corrected .env schema for HF Spaces deploy

Browse files
Files changed (4) hide show
  1. .dockerignore +71 -0
  2. .env.example +32 -15
  3. Dockerfile +58 -0
  4. README.md +1 -1
.dockerignore ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # =============================================================================
2
+ # .dockerignore β€” keep the build context tiny.
3
+ # Everything not needed by the backend runtime is excluded.
4
+ # =============================================================================
5
+
6
+ # --- VCS / IDE ---------------------------------------------------------------
7
+ .git
8
+ .github
9
+ .gitignore
10
+ .gitattributes
11
+ .vscode
12
+ .idea
13
+ *.swp
14
+
15
+ # --- Python caches & build artefacts -----------------------------------------
16
+ __pycache__
17
+ *.py[cod]
18
+ *$py.class
19
+ *.egg-info
20
+ .eggs
21
+ build
22
+ dist
23
+ .pytest_cache
24
+ .mypy_cache
25
+ .ruff_cache
26
+ .coverage
27
+ .coverage.*
28
+ htmlcov
29
+ .tox
30
+
31
+ # --- Virtual envs ------------------------------------------------------------
32
+ .venv
33
+ venv
34
+ env
35
+
36
+ # --- Frontend (deployed separately to Vercel) --------------------------------
37
+ frontend
38
+ node_modules
39
+
40
+ # --- Tests, notebooks, docs --------------------------------------------------
41
+ tests
42
+ notebooks
43
+ docs
44
+ assets
45
+ scripts
46
+
47
+ # --- Local dev / secrets -----------------------------------------------------
48
+ .env
49
+ .env.*
50
+ !.env.example
51
+ *.local
52
+
53
+ # --- OS junk -----------------------------------------------------------------
54
+ .DS_Store
55
+ Thumbs.db
56
+
57
+ # --- Docker / CI configs (not needed inside the image) -----------------------
58
+ Dockerfile
59
+ .dockerignore
60
+ .pre-commit-config.yaml
61
+ Makefile
62
+ CLAUDE.md
63
+
64
+ # --- Lockfiles / dev-only deps -----------------------------------------------
65
+ requirements-dev.txt
66
+ requirements-eval.txt
67
+
68
+ # --- Model artefacts: keep ONLY the production version -----------------------
69
+ # (Add explicit exceptions here if you publish multiple versions.)
70
+ models/**/*.tar
71
+ models/**/*.zip
.env.example CHANGED
@@ -3,33 +3,50 @@
3
  # -----------------------------------------------------------------------------
4
  # Copy this file to `.env` (which is gitignored) and fill in real values.
5
  # `pydantic-settings` automatically reads `.env` at startup and validates each
6
- # field. Variables prefixed CAPTIONING__ override nested config keys (see
7
- # `src/captioning/config/schema.py`); double underscore is the nesting delimiter.
8
  #
9
- # Example: CAPTIONING__TRAIN__BATCH_SIZE=32 overrides AppConfig.train.batch_size.
 
 
 
 
10
  # =============================================================================
11
 
12
  # ---- App-wide ----------------------------------------------------------------
13
  APP_ENV=development # development | staging | production
14
  LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR
15
 
16
- # ---- Backend (FastAPI) -------------------------------------------------------
17
- PORT=8000
18
- # Directory where weights/vocab are downloaded at startup. Empty in the image
19
- # layer; populated by `huggingface_hub.snapshot_download`. Use a writable path.
20
- MODEL_DIR=./models/cache
21
- MAX_UPLOAD_BYTES=10485760 # 10 MB; rejects oversized images
22
- # Comma-separated list of allowed origins for CORS. In production, the Vercel
23
- # frontend URL only. NEVER use "*" in prod.
24
- CORS_ALLOWED_ORIGINS=http://localhost:3000,https://your-frontend.vercel.app
25
-
26
- # ---- HuggingFace Hub (model artefact storage) --------------------------------
27
- # Public model repo holding the trained weights, vocab.pkl, config.yaml.
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  HF_REPO_ID=your-username/captioning-weights
29
  HF_REVISION=v1.0.0 # Pin a specific tag for reproducibility
30
  # Optional: only needed for private repos or higher rate limits.
31
  # Generate at https://huggingface.co/settings/tokens (read-only is enough).
32
  HF_TOKEN=
 
33
 
34
  # ---- Experiment tracking (MLflow) --------------------------------------------
35
  # Local SQLite during dev; DagsHub URL in production.
 
3
  # -----------------------------------------------------------------------------
4
  # Copy this file to `.env` (which is gitignored) and fill in real values.
5
  # `pydantic-settings` automatically reads `.env` at startup and validates each
6
+ # field.
 
7
  #
8
+ # Two prefixes are read by the application:
9
+ # BACKEND_* -> backend/app/core/config.py (BackendSettings)
10
+ # CAPTIONING__<sec>__<k> -> src/captioning/config/schema.py (AppConfig)
11
+ # Nested AppConfig fields use a double-underscore delimiter:
12
+ # CAPTIONING__TRAIN__BATCH_SIZE=32 overrides AppConfig.train.batch_size
13
  # =============================================================================
14
 
15
  # ---- App-wide ----------------------------------------------------------------
16
  APP_ENV=development # development | staging | production
17
  LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR
18
 
19
+ # ---- BackendSettings (FastAPI process) --------------------------------------
20
+ BACKEND_CONFIG_PATH=configs/base.yaml
21
+ BACKEND_WEIGHTS_PATH=models/v1.0.0/model.h5
22
+ BACKEND_TOKENIZER_DIR=models/v1.0.0
23
+ BACKEND_MODEL_VERSION=v1.0.0
24
+ BACKEND_API_VERSION=0.1.0
25
+ BACKEND_WARMUP=true
26
+ BACKEND_REQUEST_ID_HEADER=x-request-id
27
+
28
+ # ---- AppConfig overrides (research-side hyperparameters) --------------------
29
+ # CORS allow-list lives in configs/base.yaml under `serve.cors_allowed_origins`.
30
+ # Override it for prod by setting the env var below to a JSON list.
31
+ # CAPTIONING__SERVE__CORS_ALLOWED_ORIGINS=["https://your-frontend.vercel.app"]
32
+ # CAPTIONING__SERVE__MAX_UPLOAD_BYTES=10485760
33
+ # CAPTIONING__INFERENCE__DECODE_STRATEGY=beam
34
+ # CAPTIONING__INFERENCE__BEAM_WIDTH=3
35
+
36
+ # ---- TensorFlow runtime tuning (optional, for HF Spaces cpu-basic) ----------
37
+ # TF_CPP_MIN_LOG_LEVEL=2 # silence INFO/WARNING from TF
38
+ # OMP_NUM_THREADS=2 # match cpu-basic vCPU count
39
+ # TF_NUM_INTEROP_THREADS=1
40
+ # TF_NUM_INTRAOP_THREADS=2
41
+
42
+ # ---- HuggingFace Hub (model artefact storage β€” wired up in WS-A4) -----------
43
+ # Public model repo holding the trained weights + vocab.json.
44
  HF_REPO_ID=your-username/captioning-weights
45
  HF_REVISION=v1.0.0 # Pin a specific tag for reproducibility
46
  # Optional: only needed for private repos or higher rate limits.
47
  # Generate at https://huggingface.co/settings/tokens (read-only is enough).
48
  HF_TOKEN=
49
+ # HF_HOME=/home/user/.cache/huggingface
50
 
51
  # ---- Experiment tracking (MLflow) --------------------------------------------
52
  # Local SQLite during dev; DagsHub URL in production.
Dockerfile ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1.7
2
+ # =============================================================================
3
+ # Dockerfile β€” FastAPI inference backend for HuggingFace Spaces (Docker SDK).
4
+ # -----------------------------------------------------------------------------
5
+ # Target: HF Spaces, hardware = cpu-basic (2 vCPU / 16 GB RAM).
6
+ # Port: 7860 (HF Spaces convention).
7
+ # User: UID 1000 named "user" (HF Spaces requirement).
8
+ # Workdir: /home/user/app (HF Spaces convention).
9
+ # Worker: uvicorn single worker β€” keeps the TF model loaded once in RAM.
10
+ # =============================================================================
11
+
12
+ FROM python:3.11-slim-bookworm
13
+
14
+ ENV PYTHONDONTWRITEBYTECODE=1 \
15
+ PYTHONUNBUFFERED=1 \
16
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
17
+ PIP_NO_CACHE_DIR=1 \
18
+ TF_CPP_MIN_LOG_LEVEL=2 \
19
+ HF_HOME=/home/user/.cache/huggingface
20
+
21
+ # libgomp1 is required by tensorflow-cpu (OpenMP runtime).
22
+ # curl is used by HEALTHCHECK.
23
+ RUN apt-get update \
24
+ && apt-get install -y --no-install-recommends libgomp1 curl \
25
+ && rm -rf /var/lib/apt/lists/*
26
+
27
+ # HF Spaces requires a non-root user with UID 1000 named "user".
28
+ RUN useradd --create-home --uid 1000 user
29
+ USER user
30
+ ENV PATH="/home/user/.local/bin:${PATH}"
31
+ WORKDIR /home/user/app
32
+
33
+ # --- Dependency layer (cached across code changes) ---------------------------
34
+ COPY --chown=user:user requirements.txt ./
35
+ RUN pip install --user --no-cache-dir -r requirements.txt
36
+
37
+ # --- Application source ------------------------------------------------------
38
+ # Copy only what the runtime needs. Build context is pruned by .dockerignore.
39
+ COPY --chown=user:user pyproject.toml README.md ./
40
+ COPY --chown=user:user src/ ./src/
41
+ COPY --chown=user:user backend/ ./backend/
42
+ COPY --chown=user:user configs/ ./configs/
43
+ COPY --chown=user:user models/ ./models/
44
+
45
+ # Install the local captioning package without re-resolving deps.
46
+ RUN pip install --user --no-cache-dir --no-deps -e .
47
+
48
+ EXPOSE 7860
49
+
50
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \
51
+ CMD curl --fail --silent http://127.0.0.1:7860/healthz || exit 1
52
+
53
+ CMD ["uvicorn", "app.main:app", \
54
+ "--app-dir", "backend", \
55
+ "--host", "0.0.0.0", \
56
+ "--port", "7860", \
57
+ "--workers", "1", \
58
+ "--log-level", "info"]
README.md CHANGED
@@ -542,7 +542,7 @@ The backend test suite ([`backend/app/tests/`](backend/app/tests/)) introduced i
542
 
543
  ### Phase 2C β€” Public deployment 🚧 (in progress)
544
 
545
- - [ ] **WS-A** β€” Backend containerisation: multi-stage `Dockerfile` (python:3.11-slim, non-root, EXPOSE 7860, HEALTHCHECK) + `.dockerignore` + `.env.example`
546
  - [ ] **WS-A4** β€” Lifespan integration with HuggingFace Hub: extend `BackendSettings` with `weights_hub_repo` / `weights_hub_revision`, call `huggingface_hub.snapshot_download` on startup when set
547
  - [ ] **WS-B** β€” Upload trained weights + tokenizer to a HuggingFace Hub model repo
548
  - [ ] **WS-C** β€” First manual deploy to a HuggingFace Space (Docker SDK, cpu-basic, port 7860, single worker)
 
542
 
543
  ### Phase 2C β€” Public deployment 🚧 (in progress)
544
 
545
+ - [x] **WS-A** β€” Backend containerisation: `Dockerfile` (python:3.11-slim, non-root UID 1000, EXPOSE 7860, HEALTHCHECK on `/healthz`) + `.dockerignore` + corrected `.env.example` schema
546
  - [ ] **WS-A4** β€” Lifespan integration with HuggingFace Hub: extend `BackendSettings` with `weights_hub_repo` / `weights_hub_revision`, call `huggingface_hub.snapshot_download` on startup when set
547
  - [ ] **WS-B** β€” Upload trained weights + tokenizer to a HuggingFace Hub model repo
548
  - [ ] **WS-C** β€” First manual deploy to a HuggingFace Space (Docker SDK, cpu-basic, port 7860, single worker)