Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions frontend/dockerfile/dockerfile2llb/convert_copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,15 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
return err
}

// cfg.opt.llbCaps can be nil in unit tests
useLink := cfg.opt.llbCaps != nil && cfg.opt.llbCaps.Supports(pb.CapMergeOp) == nil && cfg.link && cfg.chmod == ""

var copyOpt []llb.CopyOption

if cfg.chown != "" {
if useLink && chownByName(cfg.chown) {
return errors.Errorf("--chown=%s: user and group names can't be resolved when used with --link, use numeric uid[:gid] instead", cfg.chown)
}
copyOpt = append(copyOpt, llb.WithUser(cfg.chown))
}

Expand Down Expand Up @@ -330,8 +336,7 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
fileOpt = append(fileOpt, llb.IgnoreCache)
}

// cfg.opt.llbCaps can be nil in unit tests
if cfg.opt.llbCaps != nil && cfg.opt.llbCaps.Supports(pb.CapMergeOp) == nil && cfg.link && cfg.chmod == "" {
if useLink {
pgID := identity.NewID()
d.cmdIndex-- // prefixCommand increases it
pgName := prefixCommand(d, name, d.prefixPlatform, &platform, env)
Expand Down Expand Up @@ -369,6 +374,17 @@ func isGitSource(src string) bool {
return false
}

// chownByName reports whether chown refers to a user or group by name rather
// than by numeric ID. Names are resolved from /etc/passwd and /etc/group of the
// FileOp base, which is empty when copying into a linked layer.
func chownByName(chown string) bool {
co, ok := llb.WithUser(chown).(llb.ChownOpt)
if !ok {
return false
}
return (co.User != nil && co.User.Name != "") || (co.Group != nil && co.Group.Name != "")
}

func containsWildcards(name string) bool {
for i := 0; i < len(name); i++ {
switch name[i] {
Expand Down
36 changes: 36 additions & 0 deletions frontend/dockerfile/dockerfile2llb/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,3 +468,39 @@ func TestSourceStateFromSourceOpWrappedCopy(t *testing.T) {
assert.Equal(t, sourceOp.Identifier, rewrittenSourceOp.Identifier)
assert.Equal(t, sourceOp.Attrs, rewrittenSourceOp.Attrs)
}

func TestCopyLinkChownByName(t *testing.T) {
t.Parallel()

caps := pb.Caps.CapSet(pb.Caps.All())

for _, tc := range []struct {
name string
chown string
mergeOp bool
err string
}{
{name: "numeric", chown: "1000:1000", mergeOp: true},
{name: "root", chown: "root:root", mergeOp: true},
{name: "user name", chown: "foo", mergeOp: true, err: "--chown=foo"},
{name: "user and group names", chown: "foo:bar", mergeOp: true, err: "--chown=foo:bar"},
{name: "group name", chown: "1000:bar", mergeOp: true, err: "--chown=1000:bar"},
{name: "user name without merge op", chown: "foo:bar"},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
df := "FROM scratch\nCOPY --link --chown=" + tc.chown + " a /b\n"
opt := ConvertOpt{}
if tc.mergeOp {
opt.LLBCaps = &caps
}
_, err := Dockerfile2LLB(appcontext.Context(), []byte(df), opt)
if tc.err == "" {
require.NoError(t, err)
return
}
require.ErrorContains(t, err, tc.err)
require.ErrorContains(t, err, "--link")
})
}
}
4 changes: 3 additions & 1 deletion frontend/dockerfile/docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1917,7 +1917,9 @@ COPY --chown=myuser:mygroup --chmod=644 files* /somedir/
When using names instead of numeric IDs, BuildKit resolves them using
`/etc/passwd` and `/etc/group` in the container's root filesystem. If these
files are missing or don't contain the specified names, the build fails.
Numeric IDs don't require this lookup.
Numeric IDs don't require this lookup. When combined with
[`--link`](#copy---link), files are copied into an empty filesystem, so names
can't be resolved and `--chown` must use numeric IDs.

The `--chown` flag is not supported when building Windows containers.

Expand Down