Skip to content

Fix image pull progress bar moving backward - #526

Open
dominikschubert wants to merge 2 commits into
mainfrom
devx-1114-make-image-pull-loading-more-stable-and-trustworthy
Open

dominikschubert wants to merge 2 commits into
mainfrom
devx-1114-make-image-pull-loading-more-stable-and-trustworthy

Conversation

@dominikschubert

@dominikschubert dominikschubert commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Motivation

While lstk start pulls the emulator image, the progress bar jumps backward, which makes the pull feel broken and untrustworthy.

Why the bar moved backward:

  • Missing byte counts: Docker sends status updates such as "Download complete" without byte counts. The bar treated them as zero progress.
  • Extraction restarts: the byte counter restarts from zero when a layer starts unpacking. Docker Desktop reports seconds there instead of bytes.
  • Late sizes: most layer sizes only arrive once each layer starts downloading, so the total grew mid-pull and the percentage shrank.
  • Non-layers counted: the image name line and small config files counted as layers. The counter then ended at something like 4/7, with the bar short of 100%.

Solution

What changed:

  • Per-layer progress only grows: events without numbers no longer erase progress, and neither does an extraction restart.
  • Only real layers count: config files, header lines and already-cached layers are excluded. The counter and the bar now cover the same layers.
  • Estimated sizes: a layer whose size isn't known yet is assumed as large as the largest known one. A layer that finishes without ever reporting a size is treated as tiny.
  • No early guessing: until any size is known, only fully finished layers move the bar.
  • Catch-up instead of freeze: a newly revealed large layer can lower the estimate. The bar then keeps its position and moves forward more slowly, so it never stops or goes backward.
  • Download and extraction phases: download counts for 80% of each layer and extraction for 20%. Docker Desktop gives no extraction progress, so the bar holds near 80% with an "Extracting" label.
  • Label only moves forward: it goes Pulling, Downloading, Extracting, Complete, without flickering between phases.
  • Retries handled: a layer that restarts its download starts its progress over.
  • Fresh bar per pull: a second pull in the same run starts from 0% instead of animating down from 100%.
  • Streams without layer announcements: the bar still works when Docker never announces layers up front. Blobs counted before a late announcement stay counted.

Known tradeoff: if small layers finish before a large one starts, the bar can still run ahead early, then slow down. Fetching exact layer sizes from the manifest before pulling would avoid that. We chose not to, to avoid an extra registry request.

Tests:

  • Recorded pulls: one real Docker Desktop pull and one hand-written classic-format pull are replayed through the bar.
  • Targeted tests: each root cause has its own unit test. They check the raw values, so reverting a fix makes them fail.
  • End-to-end test: lstk start runs against a fake Docker Engine API that streams the real pull. It checks every rendered frame. It fails on main, with 17 backward frames and the counter ending at 4/7, and passes with the fix.
    • It runs serially, because lstk start needs the fixed service port range 4510-4559, which the Docker-backed tests also use.
Docs

Nothing to document. The pull progress bar behaves differently, but no commands, flags, env vars or config are added or changed.

Review

Human review advised: this changes user-facing terminal behavior and adds a new fake Docker Engine test helper.

That said, to make review easier, I've recorded the new behavior here:

Old

Screen.Recording.2026-09-30.at.21.03.34.mov

New

Screen.Recording.2026-09-30.at.21.05.41.mov

Note

The layer counter now matches the image's real layer count. For localstack/localstack-pro:latest it shows 23/23 instead of 24, because the "Pulling from" header line and non-layer blobs are no longer counted.

Follow-ups

  • Optional follow-up: show "Retrying" in the pull label while Docker retries a layer. Today the bar just pauses.
  • Optional follow-up: show a clearer error when the connection to Docker drops mid-pull. Today the summary is just "unexpected EOF".

Co-Authored-By: Claude noreply@anthropic.com
馃 Generated with Claude Code

Closes DEVX-1114

@dominikschubert dominikschubert added semver: patch docs: skip Pull request does not require documentation changes labels Sep 30, 2026
dominikschubert and others added 2 commits September 30, 2026 21:13
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
@dominikschubert
dominikschubert force-pushed the devx-1114-make-image-pull-loading-more-stable-and-trustworthy branch from 27bb27c to 9a623fc Compare September 30, 2026 19:13
@dominikschubert
dominikschubert marked this pull request as ready for review September 30, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs: skip Pull request does not require documentation changes semver: patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant