WCOW: apply Linux layers and cross-OS COPY --from (partial #4537)#6880
Open
rzlink wants to merge 1 commit into
Open
WCOW: apply Linux layers and cross-OS COPY --from (partial #4537)#6880rzlink wants to merge 1 commit into
rzlink wants to merge 1 commit into
Conversation
7eceb60 to
e49b2e9
Compare
Add cross-platform layer transforms so a Windows BuildKit worker can apply Linux layers and read them via cross-OS COPY. Previously only the LCOW direction (Windows layers on Linux hosts) was supported. * util/winlayers: OS-aware context API (SetLayerOS / GetLayerOS) replaces the boolean windowsLayerMode; add applyLinuxLayer that wraps a Linux tar under Files/ and imports it via hcsshim.ociwclayer.ImportLayerFromTar; drop the Linux-only build tags from the applier. * util/winlayers: when ImportLayerFromTar's ProcessBaseLayer step rejects Linux content, strip everything except the Files/ tree and finalize the snapshot with hcsshim.ConvertToBaseLayer (which generates the registry hives and layer VHDs); stamp it with a .cross-os-linux marker. * snapshot/localmounter_windows.go: when a windows-layer mount targets a parent carrying the marker, bypass HCS and bind-filter the parent's Files/ directly, since HCS PrepareLayer cannot expose Linux content as a Windows volume. * source/containerimage/pull.go, cache/blobs.go, cache/refs.go: tag cross-platform layers in both directions. * Tests: unit coverage for the tar transforms, context API, PAX records and winDiffer.Compare() dispatch; testCopyCrossPlatformMultiStage integration test exercising real cross-OS COPY. Signed-off-by: Dawei Wei <wei.dawei.cn@gmail.com>
e49b2e9 to
b01f368
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds bidirectional cross-platform layer handling so BuildKit can apply and read image layers whose OS differs from the worker host (notably enabling a Windows worker to ingest Linux layers and support COPY --from across OS boundaries). It replaces the prior Windows-layer boolean mode with an OS-aware context mechanism and threads the layer OS through pull/cache/apply/diff paths.
Changes:
- Introduces an OS-aware winlayers context API (
SetLayerOS/GetLayerOS) and routes apply/diff behavior based on layer OS vs host OS. - Implements Windows-host application of Linux layers by wrapping Linux tars as Windows layers and importing via HCS, plus adds a marker file and Windows localmounter bypass for reads.
- Adds unit tests for tar transforms and dispatch, plus an integration test exercising cross-OS multi-stage
COPY --from.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| util/winlayers/winlayers_test.go | Adds unit coverage for context API, tar wrapping/filtering, and differ dispatch. |
| util/winlayers/differ.go | Routes Compare based on layer OS and refactors Windows tar wrapping into writeWrappedWindowsLayer. |
| util/winlayers/context.go | Replaces boolean “windows layer mode” with OS string in context and host-aware transformation checks. |
| util/winlayers/apply_windows.go | Adds Windows-only Linux-layer import via HCS and writes a cross-OS marker; parses parent layer paths. |
| util/winlayers/apply_other.go | Non-Windows stubs for Windows-only Linux-layer import helpers. |
| util/winlayers/applier.go | Splits apply into Windows-layer-on-Linux vs Linux-layer-on-Windows handlers; adds Linux-to-Windows tar wrapping pipeline. |
| source/containerimage/pull.go | Sets layer type based on requested platform OS when pulling cross-platform images. |
| snapshot/localmounter_windows.go | Adds cross-OS marker detection to bypass HCS and bind-mount parent Files/ for reading. |
| frontend/dockerfile/dockerfile_test.go | Adds integration test for cross-OS multi-stage COPY --from. |
| cache/refs.go | Propagates layer OS into context using the new API. |
| cache/manager_test.go | Adds tests around layer type propagation and cross-platform detection. |
| cache/blobs.go | Treats non-empty layer type as “cross-platform” for diffing decisions and sets layer OS in context. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+128
to
+131
| bklog.G(ctx).Infof("linuxlayer-apply: enter desc.digest=%s desc.size=%d media=%s mounts=%d", desc.Digest, desc.Size, desc.MediaType, len(mounts)) | ||
| for i, m := range mounts { | ||
| bklog.G(ctx).Infof("linuxlayer-apply: mount[%d] type=%s source=%s target=%s opts=%v", i, m.Type, m.Source, m.Target, m.Options) | ||
| } |
Comment on lines
+159
to
+164
| parents := parseParentLayerPaths(m.Options) | ||
| if len(parents) == 0 { | ||
| return "", false | ||
| } | ||
| parent := parents[0] | ||
| if _, err := os.Stat(filepath.Join(parent, crossOSLinuxMarker)); err != nil { |
Comment on lines
+113
to
+125
| func getParentLayerPaths(mounts []mount.Mount) []string { | ||
| for _, m := range mounts { | ||
| for _, opt := range m.Options { | ||
| if after, ok := strings.CutPrefix(opt, "parentLayerPaths="); ok { | ||
| var paths []string | ||
| if err := json.Unmarshal([]byte(after), &paths); err == nil { | ||
| return paths | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return nil | ||
| } |
Comment on lines
+32
to
+38
| // ProcessBaseLayer checks the process token, not the thread impersonation | ||
| // token RunWithPrivileges sets, so enable privileges process-wide. | ||
| requiredPrivileges := []string{winio.SeBackupPrivilege, winio.SeRestorePrivilege, winio.SeSecurityPrivilege} | ||
| if err := winio.EnableProcessPrivileges(requiredPrivileges); err != nil { | ||
| return 0, errors.Wrap(err, "failed to enable required privileges") | ||
| } | ||
| defer winio.DisableProcessPrivileges(requiredPrivileges) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #4537 (partial implementation — see "Scope" below).
Relates to #5758
Summary
Adds cross-platform layer support so a Windows BuildKit worker can apply Linux image layers and read them through cross-OS
COPY --from. Before this changeutil/winlayersonly handled the LCOW direction (Windows layers on Linux hosts); the Windows-applies-Linux direction was unimplemented.This implements the core of #5758 (basic cross-platform builds from Windows) for alpine-class base images: the
hcsshim::ProcessBaseLayer ... cannot find the path specifiedfailure reported there is exactly what the base-layer finalization path below resolves.How it works
applyLinuxLayerwraps the Linux tar underFiles/and imports it viahcsshim.ociwclayer.ImportLayerFromTar. When theProcessBaseLayerstep rejects Linux content, the snapshot is finalized withhcsshim.ConvertToBaseLayerand stamped with a.cross-os-linuxmarker.A windows-layer mount on a marked parent bypasses HCS and bind-filters the parent's
Files/directly, since HCSPrepareLayercannot expose Linux content as a Windows volume.The boolean
windowsLayerModeis replaced by an OS-aware context API (SetLayerOS/GetLayerOS), and cross-platform layers are tagged in both directions.Scope
#4537 asks for the cross-OS layer transform to work both directions on a Windows worker:
COPY --from=<linux-stage>into a Windows final stage.COPY/file operations on it, and committing/diffing it back into a Linux-format layer without HCS.Only the first direction is implemented here. The emit/generate direction requires non-HCS writable-layer storage (e.g. an in-process plain-directory snapshotter) plus a Windows-tolerant Linux applier/differ, and is left to a follow-up. Cross-OS
RUNremains unsupported in both directions (no Linux kernel on a Windows worker), as noted in #4537.Therefore this PR is one half of it.
Tests
winDiffer.Compare()dispatch (util/winlayers/winlayers_test.go).testCopyCrossPlatformMultiStageintegration test exercising a real cross-OSCOPY --frombuild.Known limitations
Some Linux base images do not yet round-trip cleanly on NTFS — e.g. paths containing characters NTFS forbids (
:in dpkg metadata) and certain relative symlinks (/etc/os-release). Handling those is deliberately left to a follow-up PR, so this does not yet fully close #5758 for ubuntu/debian-class images.