[PR #126] [MERGED] fix(images): real sha256 config-digest image IDs (commit + infra) #126

Closed
opened 2026-10-15 12:52:12 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/games-on-whales/LXC2Docker/pull/126
Author: @JBailes
Created: 7/1/2026
Status: ✅ Merged
Merged: 7/1/2026
Merged by: @JBailes

Base: main ← Head: fix/config-digest-commit


📝 Commits (2)

  • 228cce8 fix(images): real sha256 config-digest image IDs (commit + infra)
  • 1e4d9b9 fix commit config-digest to hash the committed snapshot, not the source

📊 Changes

7 files changed (+132 additions, -16 deletions)

View changed files

➕ internal/api/config_digest_test.go (+55 -0)
📝 internal/api/image_save.go (+36 -0)
📝 internal/api/images.go (+16 -5)
📝 internal/api/portainer.go (+1 -3)
📝 internal/api/portainer_ops.go (+12 -1)
📝 internal/api/system.go (+8 -7)
📝 internal/store/store.go (+4 -0)

📄 Description

Design-approved deferred item (Option A), part 1 of 2 — commit + shared infra. Build's aux.ID follows in a separate PR.

Problem

POST /commit returned Id: "sha256:commit_<uuid>" — not a real digest, so docker inspect <that-id> failed. Docker's image ID is the sha256 of the image's OCI config JSON.

Fix

  • Add store.ImageRecord.ConfigDigest (64-hex; omitempty) and computeConfigDigest(rec) — reuses the existing save pipeline (openImageRootfs + writeLayerTar + synthesiseImageConfig), so the stored digest equals the <config>.json name docker save would write (self-consistent).
  • Commit computes + stores it (best-effort; falls back to the internal id on tar error) and returns sha256:<digest>.
  • Surface it as the image ID everywhere via a new imageDisplayID(rec) (config digest when known, else the internal id for legacy records): inspect Id, /images/json, /system/df, image history, and the rmi Deleted line.
  • findImageByID now also matches ConfigDigest (exact + ≥4-char prefix), so docker inspect/rmi by the digest resolve.

Design notes / blast radius

  • Legacy records are unchanged — empty ConfigDigest falls back to rec.ID at every display site (byte-identical output for pulled/distro/loaded images).
  • rec.ID remains the internal grouping/lookup key (listImages/df grouping, imageRefsForID, rmi untag) — not touched. ConfigDigest is 1:1 with rec.ID (copied on docker tag), so grouping stays consistent.
  • RootFS.Layers (a layer diff-id placeholder, not the image ID) is intentionally left as-is.

Tests

config_digest_test.go — imageDisplayID (digest wins / legacy fallback) and findImageByID resolving by full digest (± sha256:), short prefix, and still by internal id.

The computeConfigDigest tar pass needs a live rootfs (like the existing save/commit tests), so it's verified by reasoning + integration CI. go test ./..., go vet, gofmt, go build clean. Merge only on verified-green CI.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/games-on-whales/LXC2Docker/pull/126 **Author:** [@JBailes](https://github.com/JBailes) **Created:** 7/1/2026 **Status:** ✅ Merged **Merged:** 7/1/2026 **Merged by:** [@JBailes](https://github.com/JBailes) **Base:** `main` ← **Head:** `fix/config-digest-commit` --- ### 📝 Commits (2) - [`228cce8`](https://github.com/games-on-whales/LXC2Docker/commit/228cce8ff92416a508873f6658a7af040afbea5f) fix(images): real sha256 config-digest image IDs (commit + infra) - [`1e4d9b9`](https://github.com/games-on-whales/LXC2Docker/commit/1e4d9b9d3b86a102808586c22d80c7611b442846) fix commit config-digest to hash the committed snapshot, not the source ### 📊 Changes **7 files changed** (+132 additions, -16 deletions) <details> <summary>View changed files</summary> ➕ `internal/api/config_digest_test.go` (+55 -0) 📝 `internal/api/image_save.go` (+36 -0) 📝 `internal/api/images.go` (+16 -5) 📝 `internal/api/portainer.go` (+1 -3) 📝 `internal/api/portainer_ops.go` (+12 -1) 📝 `internal/api/system.go` (+8 -7) 📝 `internal/store/store.go` (+4 -0) </details> ### 📄 Description Design-approved deferred item (Option A), **part 1 of 2** — commit + shared infra. Build's `aux.ID` follows in a separate PR. ## Problem `POST /commit` returned `Id: "sha256:commit_<uuid>"` — not a real digest, so `docker inspect <that-id>` failed. Docker's image ID is the **sha256 of the image's OCI config JSON**. ## Fix - Add `store.ImageRecord.ConfigDigest` (64-hex; `omitempty`) and `computeConfigDigest(rec)` — reuses the existing save pipeline (`openImageRootfs` + `writeLayerTar` + `synthesiseImageConfig`), so the stored digest equals the `<config>.json` name `docker save` would write (self-consistent). - **Commit** computes + stores it (best-effort; falls back to the internal id on tar error) and returns `sha256:<digest>`. - Surface it as the image ID everywhere via a new `imageDisplayID(rec)` (config digest when known, else the internal id for legacy records): inspect `Id`, `/images/json`, `/system/df`, image history, and the rmi `Deleted` line. - `findImageByID` now also matches `ConfigDigest` (exact + ≥4-char prefix), so `docker inspect`/`rmi` **by the digest** resolve. ## Design notes / blast radius - **Legacy records are unchanged** — empty `ConfigDigest` falls back to `rec.ID` at every display site (byte-identical output for pulled/distro/loaded images). - `rec.ID` remains the **internal grouping/lookup key** (listImages/df grouping, `imageRefsForID`, rmi untag) — not touched. `ConfigDigest` is 1:1 with `rec.ID` (copied on `docker tag`), so grouping stays consistent. - `RootFS.Layers` (a layer diff-id placeholder, not the image ID) is intentionally left as-is. ## Tests `config_digest_test.go` — `imageDisplayID` (digest wins / legacy fallback) and `findImageByID` resolving by full digest (± `sha256:`), short prefix, and still by internal id. The `computeConfigDigest` tar pass needs a live rootfs (like the existing save/commit tests), so it's verified by reasoning + integration CI. `go test ./...`, `go vet`, `gofmt`, `go build` clean. Merge only on verified-green CI. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-15 12:52:12 +00:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/LXC2Docker#126
No description provided.