From 7e934aa270ca0d4fafb0967730979e351424b2fe Mon Sep 17 00:00:00 2001 From: chetanr25 Date: Tue, 23 Jun 2026 17:48:10 +0530 Subject: [PATCH 1/4] Dockerfiles + compose: perf(docker): faster image builds and container startup --- docker/dev/Dockerfile | 19 ++++++++++++++----- docker/dev/compose.yml | 4 ++++ docker/prod/Dockerfile | 26 +++++++++++++++++++------- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index ad4bfd4..a5a42c1 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -3,7 +3,7 @@ FROM python:3.11-slim WORKDIR /app -# Use apt cache mount to speed up system package installation across builds +# apt cache mounts keep downloaded .debs across builds RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt \ @@ -11,13 +11,22 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ curl \ libgl1 \ libglib2.0-0 \ - libxcb1 + libxcb1 \ + libpq-dev \ + build-essential \ + g++ + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv COPY requirements.txt . -# Use pip cache mount so it remembers downloaded wheels -RUN --mount=type=cache,target=/root/.cache/pip \ - pip install -r requirements.txt +RUN --mount=type=cache,target=/root/.cache/uv \ + UV_TORCH_BACKEND=cpu \ + uv pip install --system -r requirements.txt + +# Bake a hash of the deps the image was built with. The entrypoint compares this +# against the live (bind-mounted) requirements.txt to decide whether to reinstall. +RUN sha256sum requirements.txt | cut -d' ' -f1 > /opt/req_hash ENV PYTHONPATH=/app diff --git a/docker/dev/compose.yml b/docker/dev/compose.yml index 83de924..58cb9d7 100644 --- a/docker/dev/compose.yml +++ b/docker/dev/compose.yml @@ -17,6 +17,8 @@ services: interval: 10s timeout: 5s retries: 5 + start_period: 30s + start_interval: 1s ollama: image: ollama/ollama:latest @@ -33,6 +35,7 @@ services: timeout: 5s retries: 5 start_period: 30s + start_interval: 2s whisper: image: onerahmet/openai-whisper-asr-webservice:latest @@ -53,6 +56,7 @@ services: timeout: 5s retries: 5 start_period: 60s + start_interval: 3s app: build: diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile index f97d6dd..ed65a28 100644 --- a/docker/prod/Dockerfile +++ b/docker/prod/Dockerfile @@ -1,32 +1,44 @@ +# ---- builder ---- FROM python:3.11-slim AS builder -WORKDIR /build +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential g++ libpq-dev && \ + rm -rf /var/lib/apt/lists/* + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv +WORKDIR /build COPY requirements.txt . -RUN pip install --no-cache-dir --prefix=/install -r requirements.txt +RUN --mount=type=cache,target=/root/.cache/uv \ + UV_TORCH_BACKEND=cpu \ + uv pip install --system -r requirements.txt +# ---- runtime ---- FROM python:3.11-slim WORKDIR /app -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ libgl1 \ libglib2.0-0 \ libxcb1 \ - && rm -rf /var/lib/apt/lists/* + libpq5 && \ + rm -rf /var/lib/apt/lists/* -COPY --from=builder /install /usr/local +COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages +COPY --from=builder /usr/local/bin /usr/local/bin -# Copy only app code, not data/ temp/ tests/ docs/ etc. COPY app/ ./app/ COPY requirements.txt . COPY docker/entrypoint.sh /entrypoint.sh +# Bake deps hash so the entrypoint can skip the redundant install when unchanged. +RUN sha256sum requirements.txt | cut -d' ' -f1 > /opt/req_hash + ENV PYTHONPATH=/app -# Data dirs created here; actual storage comes from mounted volumes at runtime. RUN mkdir -p /data/db /data/uploads && chmod +x /entrypoint.sh EXPOSE 8000 From 9f088a8debb0a6459b8b37377206beb94ce053d8 Mon Sep 17 00:00:00 2001 From: chetanr25 Date: Tue, 23 Jun 2026 17:48:39 +0530 Subject: [PATCH 2/4] fast make workflow and runtime dependency sync --- Makefile | 36 +++++++++++++++++++++++------------- docker/entrypoint.sh | 19 +++++++++++++++++-- scripts/setup-dockers-env.sh | 6 +++++- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 7d1d357..3b9a95f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help init fireform build up down logs logs-app logs-ollama shell pull-model test clean super-clean +.PHONY: help init fireform build up down logs logs-app logs-ollama shell pull-model test clean super-clean status ready-banner sync COMPOSE = docker compose -f docker/dev/compose.yml --env-file docker/.env.dev ENV_DEV = docker/.env.dev @@ -22,6 +22,8 @@ help: @echo "make build - Build Docker images" @echo "make up - Start all containers (detached)" @echo "make down - Stop all containers" + @echo "make sync - Fast-install new requirements.txt deps into running app (no rebuild)" + @echo "make status - Show compact container health summary" @echo "make logs - Stream all container logs" @echo "make logs-app - Stream app container logs" @echo "make logs-ollama - Stream Ollama container logs" @@ -43,30 +45,38 @@ init: *) echo "Run 'make fireform' when ready." ;; \ esac -fireform: build up - @printf "Waiting for Ollama to be ready..." - @until $(COMPOSE) exec -T ollama ollama list > /dev/null 2>&1; do \ - printf '.'; sleep 2; \ - done - @echo " ready." +fireform: + @$(COMPOSE) up -d --build @if $(COMPOSE) exec -T ollama ollama list 2>/dev/null | grep -q "^$(OLLAMA_MODEL)"; then \ echo " Model $(OLLAMA_MODEL) already pulled."; \ else \ echo " Pulling $(OLLAMA_MODEL)..."; \ $(COMPOSE) exec -T ollama ollama pull $(OLLAMA_MODEL); \ fi - @echo "" - @echo "FireForm is ready!" - @echo " API: http://localhost:8000" - @echo " API Docs: http://localhost:8000/docs" - @echo "" - @echo "Run 'make logs' to view live logs, 'make down' to stop." + @$(MAKE) --no-print-directory ready-banner build: @$(COMPOSE) build up: @$(COMPOSE) up -d + @$(MAKE) --no-print-directory ready-banner + +# Fast path for "I added a package": install the delta into the running container +# (no image rebuild, no 1.6GB layer re-export). uv installs only what's missing in +sync: + @$(COMPOSE) exec -T app sh -c "UV_TORCH_BACKEND=cpu uv pip install --system -r requirements.txt" + +status: + @$(COMPOSE) ps --format 'table {{.Service}}\t{{.Status}}' + +ready-banner: + @echo "" + @echo "FireForm is ready!" + @echo " API: http://localhost:8000" + @echo " API Docs: http://localhost:8000/docs" + @echo "" + @echo "Run 'make logs' to view live logs, 'make down' to stop." down: @$(COMPOSE) down --remove-orphans diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 8694d9f..a4832be 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,10 +1,25 @@ #!/bin/sh set -e -# Ensure data directories exist (volumes may be empty on first run) mkdir -p /data/uploads -# Run DB migrations / init before starting the server +# Reinstall deps only when the live requirements.txt differs from what the image +# was built with. The image bakes the hash at /opt/req_hash; in dev the live file +# comes from the bind mount. Matching hash => deps already baked in => skip (instant). +BAKED_HASH=$(cat /opt/req_hash 2>/dev/null || echo "none") +LIVE_HASH=$(sha256sum requirements.txt 2>/dev/null | cut -d' ' -f1 || echo "unknown") + +if [ "$BAKED_HASH" = "$LIVE_HASH" ]; then + echo "[entrypoint] dependencies up to date — skipping install" +else + echo "[entrypoint] requirements.txt changed since image build — syncing deps..." + if command -v uv > /dev/null 2>&1; then + UV_TORCH_BACKEND=cpu uv pip install --system -r requirements.txt + else + pip install -r requirements.txt + fi +fi + python3 -m app.db.init_db exec "$@" diff --git a/scripts/setup-dockers-env.sh b/scripts/setup-dockers-env.sh index 90adb5c..17418ad 100644 --- a/scripts/setup-dockers-env.sh +++ b/scripts/setup-dockers-env.sh @@ -1,4 +1,8 @@ #!/bin/bash source venv/bin/activate -pip install -r requirements.txt +if command -v uv > /dev/null 2>&1; then + uv pip install -r requirements.txt +else + pip install -r requirements.txt +fi From 501d837ebc16666ee59c5fd56993a3e11080fb40 Mon Sep 17 00:00:00 2001 From: chetanr25 Date: Tue, 23 Jun 2026 17:49:19 +0530 Subject: [PATCH 3/4] updated package in ci-cd --- .github/workflows/lint.yml | 7 ++++--- .github/workflows/tests.yml | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1652a2b..97bd836 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,10 +19,11 @@ jobs: with: python-version: "3.11" + - name: Install uv + uses: astral-sh/setup-uv@v6 + - name: Install linter - run: | - python -m pip install --upgrade pip - pip install ruff + run: uv pip install --system ruff - name: Run linter run: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0c90b98..4453614 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,10 +18,11 @@ jobs: with: python-version: "3.11" + - name: Install uv + uses: astral-sh/setup-uv@v6 + - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt + run: uv pip install --system -r requirements.txt - name: Run tests env: From 0e3217f75f98f60c4a25e20958cfb5c710f188b9 Mon Sep 17 00:00:00 2001 From: chetanr25 Date: Tue, 23 Jun 2026 18:11:26 +0530 Subject: [PATCH 4/4] fixed redis late start time --- docker/dev/compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/dev/compose.yml b/docker/dev/compose.yml index 83e1d82..820711d 100644 --- a/docker/dev/compose.yml +++ b/docker/dev/compose.yml @@ -72,6 +72,8 @@ services: interval: 10s timeout: 5s retries: 5 + start_period: 30s + start_interval: 1s app: build: