Skip to content

Commit 3c2df0f

Browse files
committed
dockerfile: fix CopyIgnoredFile for context root
Avoid treating COPY . . as copying an ignored file named "." when .dockerignore excludes dotfiles with patterns such as .*. Keep the warning for catch-all root patterns like *, where copying the context root would copy only ignored entries. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
1 parent cf8493e commit 3c2df0f

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

frontend/dockerfile/dockerfile2llb/validations.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/moby/buildkit/frontend/dockerfile/parser"
1616
"github.com/moby/buildkit/frontend/dockerfile/shell"
1717
"github.com/moby/buildkit/util/suggest"
18+
"github.com/moby/patternmatcher"
1819
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1920
"github.com/pkg/errors"
2021
)
@@ -46,6 +47,13 @@ func validateCopySourcePath(src string, cfg *copyConfig) error {
4647
}
4748

4849
src = filepath.ToSlash(filepath.Clean(src))
50+
if src == "." || src == "/" {
51+
// "." and "/" are context roots, not real paths that can be excluded.
52+
// Only keep the warning for patterns that exclude all root entries.
53+
if !copySourceRootIgnored(cfg.ignoreMatcher) {
54+
return nil
55+
}
56+
}
4957
ok, err := cfg.ignoreMatcher.MatchesOrParentMatches(src)
5058
if err != nil {
5159
return err
@@ -58,6 +66,19 @@ func validateCopySourcePath(src string, cfg *copyConfig) error {
5866
return nil
5967
}
6068

69+
func copySourceRootIgnored(matcher *patternmatcher.PatternMatcher) bool {
70+
for _, pattern := range matcher.Patterns() {
71+
if pattern.Exclusion() {
72+
continue
73+
}
74+
switch pattern.String() {
75+
case "*", "**", "**/*":
76+
return true
77+
}
78+
}
79+
return false
80+
}
81+
6182
func validateCircularDependency(states []*dispatchState) error {
6283
var visit func(*dispatchState, []instructions.Command) []instructions.Command
6384
if states == nil {

frontend/dockerfile/dockerfile_lint_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var lintTests = integration.TestFuncs(
4848
testInvalidDefaultArgInFrom,
4949
testFromPlatformFlagConstDisallowed,
5050
testCopyIgnoredFiles,
51+
testCopyIgnoredFileContextRoot,
5152
testDefinitionDescription,
5253
testExposeProtoCasing,
5354
testExposeInvalidFormat,
@@ -242,6 +243,41 @@ COPY . .
242243
})
243244
}
244245

246+
func testCopyIgnoredFileContextRoot(t *testing.T, sb integration.Sandbox) {
247+
dockerfile := []byte(`
248+
FROM scratch
249+
COPY . .
250+
`)
251+
252+
t.Run("dotfiles", func(t *testing.T) {
253+
checkLinterWarnings(t, sb, &lintTestParams{
254+
Dockerfile: dockerfile,
255+
DockerIgnore: []byte(`
256+
.*
257+
`),
258+
})
259+
})
260+
261+
t.Run("wildcard", func(t *testing.T) {
262+
checkLinterWarnings(t, sb, &lintTestParams{
263+
Dockerfile: dockerfile,
264+
DockerIgnore: []byte(`
265+
*
266+
`),
267+
Warnings: []expectedLintWarning{
268+
{
269+
RuleName: "CopyIgnoredFile",
270+
Description: "Attempting to Copy file that is excluded by .dockerignore",
271+
Detail: `Attempting to Copy file "." that is excluded by .dockerignore`,
272+
URL: "https://docs.docker.com/go/dockerfile/rule/copy-ignored-file/",
273+
Level: 1,
274+
Line: 3,
275+
},
276+
},
277+
})
278+
})
279+
}
280+
245281
func testSecretsUsedInArgOrEnv(t *testing.T, sb integration.Sandbox) {
246282
dockerfile := []byte(`# check=skip=InvalidDefinitionDescription
247283

0 commit comments

Comments
 (0)