From ac9d994a080a942c0a6d0907deda08dcddf6f693 Mon Sep 17 00:00:00 2001 From: Horizon_Architect_07 Date: Mon, 30 Mar 2026 21:36:20 +0000 Subject: [PATCH 1/5] fix: make Dockerfile self-contained with multi-stage build --- Dockerfile | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 25d27d46c6d..91ff16f0014 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,28 @@ +# ---- Stage 1: Builder ---- +FROM docker.io/library/node:20-slim AS builder + +# Install git (needed by generate-git-commit-info.js script) +RUN apt-get update && apt-get install -y --no-install-recommends git \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +# Copy ALL source files needed for build +COPY package*.json ./ +COPY packages/ ./packages/ +COPY tsconfig*.json ./ +COPY eslint.config.js ./ +COPY scripts/ ./scripts/ +COPY esbuild.config.js ./ +COPY .git/ ./.git/ + +# Skip husky (no need in Docker), install deps and build +RUN HUSKY=0 npm install && \ + HUSKY=0 npm run build && \ + npm pack -w packages/core --pack-destination packages/core/dist/ && \ + npm pack -w packages/cli --pack-destination packages/cli/dist/ + +# ---- Stage 2: Runtime (original Dockerfile, unchanged) ---- FROM docker.io/library/node:20-slim ARG SANDBOX_NAME="gemini-cli-sandbox" @@ -39,9 +64,11 @@ ENV PATH=$PATH:/usr/local/share/npm-global/bin # switch to non-root user node USER node +# Copy built artifacts from builder stage (no host pre-build needed!) +COPY --from=builder /build/packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz +COPY --from=builder /build/packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz + # install gemini-cli and clean up -COPY packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz -COPY packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz RUN npm install -g /tmp/gemini-core.tgz \ && npm install -g /tmp/gemini-cli.tgz \ && node -e "const fs=require('node:fs'); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json','utf8')); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json','utf8'));" \ @@ -50,4 +77,4 @@ RUN npm install -g /tmp/gemini-core.tgz \ && rm -f /tmp/gemini-{cli,core}.tgz # default entrypoint when none specified -CMD ["gemini"] +ENTRYPOINT ["/usr/local/share/npm-global/bin/gemini"] \ No newline at end of file From 1daafe4dc166b41e6fa77c1d6166099567ab0c9a Mon Sep 17 00:00:00 2001 From: Horizon_Architect_07 Date: Wed, 1 Apr 2026 07:50:34 +0000 Subject: [PATCH 2/5] fix(docker): apply reviewer suggestions for caching and reliability --- Dockerfile | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 91ff16f0014..5dec2d4536c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,22 +7,38 @@ RUN apt-get update && apt-get install -y --no-install-recommends git \ WORKDIR /build -# Copy ALL source files needed for build +# Copy only package.json files first for better layer caching +# Dependencies only re-install when package files change, not source files COPY package*.json ./ +COPY packages/cli/package*.json ./packages/cli/ +COPY packages/core/package*.json ./packages/core/ +COPY packages/vscode-ide-companion/package*.json ./packages/vscode-ide-companion/ +COPY packages/vscode-ide-companion/scripts/ ./packages/vscode-ide-companion/scripts/ +COPY packages/devtools/package*.json ./packages/devtools/ +COPY packages/sdk/package*.json ./packages/sdk/ +COPY packages/test-utils/package*.json ./packages/test-utils/ +COPY packages/a2a-server/package*.json ./packages/a2a-server/ + +# Use npm ci for consistent, reliable builds (respects package-lock.json) +RUN HUSKY=0 npm ci --ignore-scripts + +# Now copy the rest of the source (after install for better caching) COPY packages/ ./packages/ COPY tsconfig*.json ./ COPY eslint.config.js ./ COPY scripts/ ./scripts/ COPY esbuild.config.js ./ -COPY .git/ ./.git/ -# Skip husky (no need in Docker), install deps and build -RUN HUSKY=0 npm install && \ - HUSKY=0 npm run build && \ +# Pass git commit hash as build arg instead of copying entire .git directory +ARG GIT_COMMIT=unknown +ENV GIT_COMMIT=$GIT_COMMIT + +# Build and pack artifacts +RUN HUSKY=0 npm run build && \ npm pack -w packages/core --pack-destination packages/core/dist/ && \ npm pack -w packages/cli --pack-destination packages/cli/dist/ -# ---- Stage 2: Runtime (original Dockerfile, unchanged) ---- +# ---- Stage 2: Runtime ---- FROM docker.io/library/node:20-slim ARG SANDBOX_NAME="gemini-cli-sandbox" @@ -68,9 +84,8 @@ USER node COPY --from=builder /build/packages/cli/dist/google-gemini-cli-*.tgz /tmp/gemini-cli.tgz COPY --from=builder /build/packages/core/dist/google-gemini-cli-core-*.tgz /tmp/gemini-core.tgz -# install gemini-cli and clean up -RUN npm install -g /tmp/gemini-core.tgz \ - && npm install -g /tmp/gemini-cli.tgz \ +# Install both packages in single command so npm resolves inter-dependencies correctly +RUN npm install -g /tmp/gemini-core.tgz /tmp/gemini-cli.tgz \ && node -e "const fs=require('node:fs'); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli/package.json','utf8')); JSON.parse(fs.readFileSync('/usr/local/share/npm-global/lib/node_modules/@google/gemini-cli-core/package.json','utf8'));" \ && gemini --version > /dev/null \ && npm cache clean --force \ From 64ab863b9574ff8cd6beb6b7ef6b0653309790f2 Mon Sep 17 00:00:00 2001 From: Horizon_Architect_07 Date: Wed, 1 Apr 2026 13:43:28 +0000 Subject: [PATCH 3/5] fix(docker): use GIT_COMMIT env var in generate-git-commit-info.js --- scripts/generate-git-commit-info.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/generate-git-commit-info.js b/scripts/generate-git-commit-info.js index 049c39c249b..b870d41ba7b 100644 --- a/scripts/generate-git-commit-info.js +++ b/scripts/generate-git-commit-info.js @@ -42,13 +42,18 @@ if (!existsSync(generatedCoreDir)) { } try { - const gitHash = execSync('git rev-parse --short HEAD', { - encoding: 'utf-8', - }).trim(); - if (gitHash) { - gitCommitInfo = gitHash; + // Check for GIT_COMMIT env var first (e.g. when building inside Docker + // without a .git directory available) + if (process.env.GIT_COMMIT) { + gitCommitInfo = process.env.GIT_COMMIT; + } else { + const gitHash = execSync('git rev-parse --short HEAD', { + encoding: 'utf-8', + }).trim(); + if (gitHash) { + gitCommitInfo = gitHash; + } } - const result = await readPackageUp(); cliVersion = result?.packageJson?.version ?? 'UNKNOWN'; } catch { From dd489db40a4c9cae2b406261bdf8390ff6380194 Mon Sep 17 00:00:00 2001 From: Horizon_Architect_07 Date: Thu, 2 Apr 2026 08:02:12 +0000 Subject: [PATCH 4/5] fix(docker): add .dockerignore to reduce build context size --- .dockerignore | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000000..e79a88e890e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +# Git history - not needed in build context +.git + +# Root node_modules - reinstalled inside container via npm ci +node_modules + +# Package-level node_modules - reinstalled inside container +packages/*/node_modules + +# Development and IDE files +.github +.vscode +npm-debug.log* + +# Misc +.DS_Store +*.tmp From 75cf83911844ba81f386bc49159c9461b0b54971 Mon Sep 17 00:00:00 2001 From: Horizon_Architect_07 Date: Sun, 5 Apr 2026 10:21:08 +0000 Subject: [PATCH 5/5] fix(docker): validate GIT_COMMIT env var before use --- scripts/generate-git-commit-info.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/generate-git-commit-info.js b/scripts/generate-git-commit-info.js index b870d41ba7b..8aafbf54112 100644 --- a/scripts/generate-git-commit-info.js +++ b/scripts/generate-git-commit-info.js @@ -44,8 +44,9 @@ if (!existsSync(generatedCoreDir)) { try { // Check for GIT_COMMIT env var first (e.g. when building inside Docker // without a .git directory available) - if (process.env.GIT_COMMIT) { - gitCommitInfo = process.env.GIT_COMMIT; + const envCommit = process.env.GIT_COMMIT; + if (envCommit && /^[0-9a-f]+$/i.test(envCommit)) { + gitCommitInfo = envCommit; } else { const gitHash = execSync('git rev-parse --short HEAD', { encoding: 'utf-8',