diff --git a/build.sh b/build.sh index 8185a9305..3fc19f6f1 100755 --- a/build.sh +++ b/build.sh @@ -41,6 +41,8 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" +export DOCKER_BUILDKIT=1 + BACKEND_ENV_FILE="$SCRIPT_DIR/backend/.env" DIST_ROOT="$SCRIPT_DIR/dist/docker" @@ -158,6 +160,17 @@ get_repo_digest() { fi } +# Pull an image only if it is not already present locally. +ensure_image_present() { + local source="$1" + if docker image inspect "$source" >/dev/null 2>&1; then + echo "[bundle] Image ${source} already present, skipping pull" + return 0 + fi + docker pull "$source" +} + + resolve_app_version() { local tag="$1" local git_commit @@ -719,8 +732,8 @@ bundle_release() { build_agent "${tag}" # Pull and tag postgres image - echo "[bundle] Pulling postgres image ${postgres_source}..." - docker pull "${postgres_source}" + echo "[bundle] Ensuring postgres image ${postgres_source}..." + ensure_image_present "${postgres_source}" docker tag "${postgres_source}" "${postgres_tag}" # Release gate: fresh PostgreSQL migration + backend boot + restart must pass. @@ -905,8 +918,8 @@ bundle_embeddings() { build_agent_embeddings "${tag}${suffix}" # Pull and tag postgres image - echo "[bundle:embeddings] Pulling postgres image ${postgres_source}..." - docker pull "${postgres_source}" + echo "[bundle:embeddings] Ensuring postgres image ${postgres_source}..." + ensure_image_present "${postgres_source}" docker tag "${postgres_source}" "${postgres_tag}" # Release gate: fresh PostgreSQL migration + backend boot + restart must pass. @@ -1023,6 +1036,9 @@ Notes: - Bundle commands (bundle, bundle:embeddings) now include postgres:16-alpine as superset-tools-postgres: — loaded together with other images via 'xz -dc ... | docker load'. No external PostgreSQL required. + - pip/npm dependency downloads are cached via BuildKit cache mounts and the + postgres pull is skipped when the image is already present locally. + Clear the dependency cache with: docker buildx prune HELP } diff --git a/docker/Dockerfile.agent b/docker/Dockerfile.agent index a52642f10..81aa503c1 100644 --- a/docker/Dockerfile.agent +++ b/docker/Dockerfile.agent @@ -26,12 +26,14 @@ RUN pip install --no-cache-dir -e /app/shared/ # Install agent requirements COPY agent/requirements.txt /app/agent/requirements.txt -RUN pip install --no-cache-dir -r /app/agent/requirements.txt +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install -r /app/agent/requirements.txt # Optional: semantic embedding routing COPY agent/requirements-embeddings.txt /app/agent/requirements-embeddings.txt -RUN if [ "$WITH_EMBEDDINGS" = "true" ]; then \ - pip install --no-cache-dir -r /app/agent/requirements-embeddings.txt; \ +RUN --mount=type=cache,target=/root/.cache/pip \ + if [ "$WITH_EMBEDDINGS" = "true" ]; then \ + pip install -r /app/agent/requirements-embeddings.txt; \ fi # Agent source code diff --git a/docker/all-in-one.Dockerfile b/docker/all-in-one.Dockerfile index 043d47b97..bb1b2d07d 100644 --- a/docker/all-in-one.Dockerfile +++ b/docker/all-in-one.Dockerfile @@ -18,7 +18,8 @@ WORKDIR /app/frontend # Install deps (layer cache when package.json unchanged) COPY frontend/package.json frontend/package-lock.json* ./ -RUN npm ci --prefer-offline --no-audit --no-fund --legacy-peer-deps +RUN --mount=type=cache,target=/root/.npm \ + npm ci --prefer-offline --no-audit --no-fund --legacy-peer-deps # Build frontend COPY frontend/ ./ @@ -43,7 +44,8 @@ RUN apt-get update \ # Python deps (NO playwright — saves ~350MB) COPY backend/requirements-backend.txt /app/backend/requirements-backend.txt -RUN pip install --no-cache-dir -r /app/backend/requirements-backend.txt +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install -r /app/backend/requirements-backend.txt # Backend source COPY backend/ /app/backend/ diff --git a/docker/backend.Dockerfile b/docker/backend.Dockerfile index b62701e55..87dad5b5b 100644 --- a/docker/backend.Dockerfile +++ b/docker/backend.Dockerfile @@ -25,14 +25,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Python зависимости — backend runtime COPY backend/requirements-backend.txt /app/backend/requirements-backend.txt -RUN pip install --no-cache-dir -r /app/backend/requirements-backend.txt +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install -r /app/backend/requirements-backend.txt # Install shared package (LLM health, SSL, cot_logger) COPY shared/ /app/shared/ RUN pip install --no-cache-dir -e /app/shared/ # Install shared LLM deps (openai, httpx for _llm_health) -RUN pip install --no-cache-dir "openai>=1.0.0" "httpx>=0.28.1" +RUN --mount=type=cache,target=/root/.cache/pip \ + pip install "openai>=1.0.0" "httpx>=0.28.1" # Browser binaries are required only by screenshot-capable deployments. API-only E2E # stacks can opt out through INSTALL_PLAYWRIGHT_BROWSERS=0 to reduce image build pressure. diff --git a/docker/frontend.Dockerfile b/docker/frontend.Dockerfile index 7f79b2a9e..9ceeb1250 100644 --- a/docker/frontend.Dockerfile +++ b/docker/frontend.Dockerfile @@ -15,7 +15,8 @@ ENV APP_VERSION=${APP_VERSION} WORKDIR /app/frontend COPY frontend/package*.json ./ -RUN npm ci --legacy-peer-deps +RUN --mount=type=cache,target=/root/.npm \ + npm ci --legacy-peer-deps COPY frontend/ ./ RUN npm run build