Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix .dockerignore resolution when using multiple Dockerfiles #863

Merged
merged 7 commits into from
Dec 11, 2023
Merged

Conversation

blampe
Copy link
Contributor

@blampe blampe commented Nov 27, 2023

This pushes .dockerignore path resolution down into getIgnorePatterns so it can juggle the multiple candidate ignore-files correctly.

Resolution follows the behavior described here:

...the build client looks for a file named .dockerignore in the root directory of the context.

If you use multiple Dockerfiles, you can use different ignore-files for each Dockerfile. [...] Place your ignore-file in the same directory as the Dockerfile, and prefix the ignore-file with the name of the Dockerfile.

A Dockerfile-specific ignore-file takes precedence over the .dockerignore file at the root of the build context if both exist.

In other words, we look for a <Dockerfile>.dockerignore file sitting next to <Dockerfile>, and if that doesn't exist we fall back on the .dockerignore at the root of our build context.

Fixes #675

@blampe blampe requested review from guineveresaenger, a team and thomas11 November 27, 2023 22:19
Copy link

Does the PR have any schema changes?

Does the PR have any schema changes?

Looking good! No breaking changes found.
No new resources/functions.

Maintainer note: consult the runbook for dealing with any breaking changes.

Comment on lines -119 to -132
func TestDockerignoreNoMappingYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}
// we expect this test to succeed, as we test that the ignore.txt file does in fact _not_ get ignored
// the ignore.txt file does not get ignored, as .dockerignore does not map to Mockerfile.
// The RUN command in Mockerfile therefore succeeds.
integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-dockerfile", "dockerignore-no-mapping"),
Quick: true,
SkipRefresh: true,
})
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was testing the bug, so I removed it.

Comment on lines -105 to -117
func TestDockerignoreDefaultFailYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}

integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-dockerfile", "dockerignore-default-fail"),
Quick: true,
SkipRefresh: true,
ExpectFailure: true,
})
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was effectively the same as the dockerignore-default test. I removed it and consolidated its assertion with the other test by adding explicit existence/non-existence checks in the Dockerfile.

Comment on lines +5 to +7
RUN [ -f "app.txt" ]

RUN [ ! -f "ignore.txt" ]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added these here and elsewhere to ensure we always build the image with the expected files.

Copy link
Contributor

@guineveresaenger guineveresaenger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good!

Can you add a bit more detail to the pull request description for posterity? A quick description of the situation where a codebase is "using multiple Dockerfiles" and how those map to .dockerignores, and a summary of how this PR fixes detection and fallback (the code comment is great but having it in the commit message is also valuable IMO)

}
defer f.Close()

ignorePatterns, err := dockerignore.ReadAll(f)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume we return on the first found .dockerignore file because we're relying on the order in which the particular .dockerignores get appended to paths (specific first, root-level second) - is there a way to make that precedence more explicit?

Copy link
Contributor Author

@blampe blampe Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly. I did some spelunking and confirmed we should always check for the presence of <Dockerfile>.dockerignore regardless of the file's name. So that makes this logic a little more explicit -- there are always 2 things to check and in a particular order.

@blampe blampe merged commit 61de332 into master Dec 11, 2023
17 checks passed
@blampe blampe deleted the 675 branch December 11, 2023 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Version 4.x: unable to hash build context ... could not open file, permission denied
3 participants