GitLab CI/CD Container Image Size Budget Gate Prompt
Add an image-size budget gate to GitLab CI — measure built image size, diff against a baseline, and fail the pipeline when a layer bloats the image past budget.
- Target user
- DevOps engineers enforcing container image size discipline in GitLab CI
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior DevOps engineer who keeps container images small in CI. You treat image size like a test: measured on every build, diffed against a baseline, and gated with a budget — because images silently bloat one careless layer at a time until pulls are slow and nodes run out of disk.
I will provide:
- The Dockerfile (or a summary) and language/runtime
- Current image size and where it's pushed (GitLab registry / external)
- Current pipeline build job YAML
- The goal (add a size gate / find the bloat / set a sane budget)
- Runner/executor (DinD, Kaniko, BuildKit)
Your job:
1. **Measure reliably**: capture the built image's size from the local daemon (`docker image inspect -f '{{.Size}}'`) or the registry manifest — not a re-pull. For Kaniko/BuildKit, read the pushed manifest size via the registry API.
2. **Establish a baseline**: the last successful image on the target branch (by digest), stored as a pipeline artifact or in the registry, so the MR diff is `new - baseline`.
3. **Define the budget**: an absolute ceiling (e.g., 250 MB) AND a per-MR delta ceiling (e.g., +15 MB), whichever is more useful; make both configurable via CI variables.
4. **Fail with actionable output**: on breach, print the size, the budget, the delta, and the top layers by size (`docker history` / `dive` JSON) so the author sees WHICH layer bloated.
5. **Provide an audited override**: a `SIZE_GATE_OVERRIDE` variable or MR label that records who bypassed and why — never a silently-editable threshold.
6. **Recommend fixes when it fails**: multi-stage build, distroless/alpine runtime, `--no-install-recommends`, cleaning apt lists in the same layer, `.dockerignore`, and dropping build tools from the runtime stage.
7. **Report as an MR artifact**: post the size table so reviewers see the trend without opening logs.
Deliverables:
- A reusable `.image-size-gate` job that measures, diffs, and fails closed
- The budget variables and the override mechanism
- The top-layers breakdown command wired into the failure path
- Concrete Dockerfile fixes if the current image is already over budget
Mark DESTRUCTIVE or RISKY: running/inspecting untrusted images on privileged runners, and any override that isn't recorded.
---
Dockerfile (summary): [DESCRIBE base, stages]
Current size + registry: [DESCRIBE]
Build job (YAML): [PASTE]
Goal: [add gate / find bloat / set budget]
Executor: [DinD / Kaniko / BuildKit]
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
Image bloat is a slow regression no single reviewer catches — each MR adds “just a few MB.” Turning size into a gated, diffed metric with a per-MR delta budget catches the regression at the exact commit that caused it and names the offending layer, which is the difference between a fix and a shrug.
How to use it
- Measure the built image locally, not via re-pull.
- Diff against the target branch’s last good digest.
- Fail on absolute ceiling or per-MR delta.
- Print the top layers so the author knows what bloated.
Useful commands
# Size of the just-built local image (bytes)
docker image inspect myapp:ci --format '{{.Size}}'
# Human-readable, and top layers by size
docker image ls myapp:ci
docker history --no-trunc --format '{{.Size}}\t{{.CreatedBy}}' myapp:ci | sort -rh | head
# Registry manifest size (no pull) via API
skopeo inspect --raw docker://$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA \
| jq '[.layers[].size] | add'
# Deep layer analysis as JSON for CI
dive --json dive.json myapp:ci
GitLab CI patterns
Reusable image-size gate
variables:
IMAGE_SIZE_MAX_MB: "250" # absolute ceiling
IMAGE_SIZE_DELTA_MB: "15" # per-MR increase ceiling
.image-size-gate:
image: docker:26.1.4
services: [docker:26.1.4-dind]
script:
- SIZE_BYTES=$(docker image inspect "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" --format '{{.Size}}')
- SIZE_MB=$(( SIZE_BYTES / 1024 / 1024 ))
- echo "Image size: ${SIZE_MB} MB (budget ${IMAGE_SIZE_MAX_MB} MB)"
- |
if [ -f baseline-size.txt ]; then
BASE_MB=$(cat baseline-size.txt); DELTA=$(( SIZE_MB - BASE_MB ))
echo "Baseline ${BASE_MB} MB, delta ${DELTA} MB (max +${IMAGE_SIZE_DELTA_MB})"
fi
- |
if [ "$SIZE_MB" -gt "$IMAGE_SIZE_MAX_MB" ] && [ "$SIZE_GATE_OVERRIDE" != "true" ]; then
echo "IMAGE OVER BUDGET — top layers:"
docker history --format '{{.Size}}\t{{.CreatedBy}}' "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" | sort -rh | head
exit 1
fi
- echo "$SIZE_MB" > baseline-size.txt
artifacts:
paths: [baseline-size.txt] # becomes next run's baseline on the default branch
Wire the gate after build
image-size:
extends: .image-size-gate
stage: test
needs: [build-image]
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
Audited override (recorded, not silent)
# Set SIZE_GATE_OVERRIDE=true as a pipeline variable when starting the job,
# and require an MR label 'size-override-approved' via a separate check:
size-override-audit:
rules:
- if: '$SIZE_GATE_OVERRIDE == "true"'
script:
- echo "Size gate overridden by $GITLAB_USER_LOGIN on pipeline $CI_PIPELINE_ID" | tee override.log
artifacts:
paths: [override.log]
expire_in: 1 year
Common findings this catches
- Steady multi-MB creep that no single review flagged, now pinned to one commit.
- A build tool (compiler,
-devpackages) left in the runtime stage. apt-get installwithout--no-install-recommendsor apt-list cleanup, inflating a layer.- Baseline compared against a moving
:latesttag, producing noisy diffs. - Gate disabled by commenting it out instead of a recorded override.
When to escalate
- A legitimate large dependency pushing past budget — raise the budget deliberately with sign-off, don’t disable the gate.
- Base-image size mandated by security/compliance — coordinate an approved baseline.
- Registry storage/bandwidth costs from large images — a capacity conversation with the platform team.
Related prompts
-
GitLab CI/CD with Docker BuildKit & Cache Optimization Prompt
Use BuildKit in GitLab CI/CD — multi-stage caching, registry cache, build secrets, multi-arch images, and avoiding the cold cache trap.
-
GitLab CI/CD Android Signed APK/AAB Build Pipeline Prompt
Build, test, and sign Android APK/AAB artifacts in GitLab CI — keystore secrecy, Gradle caching, SDK licenses, and Play Store upload without leaking signing keys.
-
GitLab CI/CD Playwright Sharded E2E Test Pipeline Prompt
Run Playwright end-to-end tests sharded across GitLab CI jobs — browser caching, blob-report merge, flaky retries, traces on failure, and a single merged HTML report.
-
GitLab CI/CD FIPS-Compliant Runner Hardening Prompt
Stand up and validate FIPS 140-compliant GitLab Runners and pipelines — FIPS images, crypto policy, verification, and avoiding silent non-compliant fallbacks.
More GitLab CI/CD prompts & error guides
Browse every GitLab CI/CD prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.