Repository: moby/moby (language: go)

Issue:
[22.06] COPY --link broken in some cases
Reported by @sudo-bmitch in slack

With the default builder `docker builder use default`

```
$ cat df.copy-link 
# syntax=docker/dockerfile:1

FROM alpine:latest as build
RUN addgroup -g 5000 appuser \
 && adduser -u 5000 -G appuser -D appuser \
 && mkdir -p /home/appuser/.config \
 && chown -R appuser /home/appuser/.config

FROM scratch as release
COPY --link --from=build /etc/passwd /etc/group /etc/
COPY --link --from=build --chown=5000:5000 /home/appuser/ /home/appuser/

$ docker build -t test-copy-link -f df.copy-link .
....
 => [build 2/2] RUN addgroup -g 5000 appuser  && adduser -u 5000 -G appuser -D appuser  && mkdir -p /home/appuser/.config  && chown -R appuser /home/appuser/.config                                          0.5s
 => [release 2/2] COPY --link --from=build --chown=5000:5000 /home/appuser/ /home/appuser/                                                                                                                    0.1s
 => ERROR exporting to image                                                                                                                                                                                  0.0s
 => => exporting layers                                                                                                                                                                                       0.0s
------
 > exporting to image:
------
error: failed to solve: can not convert active kjb10koor6qk2zaa57bn3q9t8 to layer
```

Fix by @sipsma is in https://github.com/sipsma/moby/commit/ab819190efd66dde0224c7fbcb54de9f8f19fbc2 that needs to be opened as a PR.

We also need to look into why the integration tests did not catch this case @crazy-max 



Discussion / hints:

Fix patch:
diff --git a/builder/builder-next/exporter/export.go b/builder/builder-next/exporter/export.go
index ee945a1150402..e138a6f23593a 100644
--- a/builder/builder-next/exporter/export.go
+++ b/builder/builder-next/exporter/export.go
@@ -160,6 +160,10 @@ func (e *imageExporterInstance) Export(ctx context.Context, inp exporter.Source,
 			return nil, layersDone(err)
 		}
 
+		if err := ref.Extract(ctx, nil); err != nil {
+			return nil, err
+		}
+
 		diffIDs, err := e.opt.Differ.EnsureLayer(ctx, ref.ID())
 		if err != nil {
 			return nil, layersDone(err)
diff --git a/builder/builder-next/worker/worker.go b/builder/builder-next/worker/worker.go
index 4cb559ede70ba..af980bfbfc247 100644
--- a/builder/builder-next/worker/worker.go
+++ b/builder/builder-next/worker/worker.go
@@ -228,7 +228,7 @@ func (w *Worker) Exporter(name string, sm *session.Manager) (exporter.Exporter,
 }
 
 // GetRemote returns a remote snapshot reference for a local one
-func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool, _ compression.Type, _ session.Group) (*solver.Remote, error) {
+func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIfNeeded bool, _ compression.Type, s session.Group) (*solver.Remote, error) {
 	var diffIDs []layer.DiffID
 	var err error
 	if !createIfNeeded {
@@ -240,6 +240,9 @@ func (w *Worker) GetRemote(ctx context.Context, ref cache.ImmutableRef, createIf
 		if err := ref.Finalize(ctx); err != nil {
 			return nil, err
 		}
+		if err := ref.Extract(ctx, s); err != nil {
+			return nil, err
+		}
 		diffIDs, err = w.Layers.EnsureLayer(ctx, ref.ID())
 		if err != nil {
 			return nil, err


Test patch: