Skip to content

build: accept -f - to read Dockerfile from stdin#31236

Merged
vdemeester merged 3 commits intomoby:masterfrom
tonistiigi:docker-stdin
Apr 10, 2017
Merged

build: accept -f - to read Dockerfile from stdin#31236
vdemeester merged 3 commits intomoby:masterfrom
tonistiigi:docker-stdin

Conversation

@tonistiigi
Copy link
Member

Choose a reason for hiding this comment

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

The comment is a bit unclear. It makes it sound like the contents of the existing tar is replaced with just one file.

Choose a reason for hiding this comment

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

Agreed, this seems very similar to replaceDockerfileTarWrapper.

Choose a reason for hiding this comment

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

Also, I would rather avoid having two nested tar stream modifications in the trusted + stdin case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it could be like a pipeline of modifications. The same pipeline steps could be also used for tar creation and extraction. Atm there is big list of specific arguments, for example user remapping, filename renaming for cp etc. while all these could be implemented as a conversion step.

@aaronlehmann
Copy link

Design LGTM

@yallop
Copy link
Contributor

yallop commented Feb 22, 2017

Why are the commits squashed here? It'd be better to have two commits, to preserve history and authorship. Could you rebase to split the commits, @tonistiigi?

Copy link
Member

Choose a reason for hiding this comment

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

Not sure how important it is for how this tar stream is used but after reading the tar content there could be remaining data that on the input tar stream, we often pipe that to null to ensure that anything blocking on that read is freed (without needing to rely on the close).

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean in case of an error? Can tarReader really skip data if it returns io.EOF

Copy link
Member

Choose a reason for hiding this comment

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

Instead of always writing at end, write when err == io.EOF or as soon as header.Name <= hdr.Name

Copy link
Member Author

Choose a reason for hiding this comment

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

I've updated this and added more tests.

@thaJeztah
Copy link
Member

We discussed this PR in the maintainers meeting and like this feature; @vieux is gonna look into adding the same for -f /path/to/a/Dockerfile as a follow up

@tonistiigi tonistiigi force-pushed the docker-stdin branch 2 times, most recently from d0d3f62 to a5da5b1 Compare February 23, 2017 22:50
Copy link
Member

Choose a reason for hiding this comment

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

What is the point of this assignment instead of just directly passing into io.Copy or assigning here. I see this as unnecessarily shadowing the arg content.

Copy link
Contributor

Choose a reason for hiding this comment

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

If someone already has a Dockerfile but its not being used for the build, and they use "-" on the -f, won't this replace their Dockerfile and cause incorrect results if their Dockerfile is used for some other purpose?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this comment needs to be updated based on the recent change you made to generate a random dockerfile name.

@duglin
Copy link
Contributor

duglin commented Mar 6, 2017

While I like the idea of this, I'm not comfortable with replacing a user-owned file with the stdin and we should be adding any files we inject into the context to .dockerignore.

My preferred solution would be to make the input of the API a multi-part mime where one section is the tar and another section is the Dockerfile. But, that's a much bigger change. Short of that, can we consider storing the stdin into a new/random file that then gets added to .dockerignore? Our goal should be to have zero impact on existing files in the context. Meaning, a Dockerfile cmd of COPY * ... should not see any new files due to this feature.

@tonistiigi
Copy link
Member Author

@duglin This is definitely harder but I'll see what I can do. Although for - I don't see much of a problem. Dockerfile is the default name that is always used unless user sets a new name with -f. If they set -f - they don't really specify the new name. But I can see it becoming more complicated when we start accepting absolute paths outside working dir for -f as well.

@cpuguy83
Copy link
Member

cpuguy83 commented Mar 7, 2017

Can't we write to some temp file within the context, add to dockerignore, and set the dockerfile path to the temp file when sending to the API? If the user wants it to be part of their context they shouldn't use stdin, I think?

@tonistiigi
Copy link
Member Author

@cpuguy83 I guess that's what @duglin was suggesting as well. Note though that even atm we don't make any promises about the contents of Dockerfile. Using content trust with COPY Dockerfile . you would not get the same contents.

@duglin
Copy link
Contributor

duglin commented Mar 7, 2017

@tonistiigi can you elaborate on your statement about the Dockerfile? With docker build -f foo . I would hope that any file in . would be totally untouched, including one named Dockerfile. So the user could put anything they wanted in there an be assured that docker won't touch it.

@duglin
Copy link
Contributor

duglin commented Mar 7, 2017

To be honest, I'm not thrilled with modifying the user's .dockerignore file either since we never claimed it was "ours". To me its the user's input to us.

Another option would be to add a flag to just the API for now (e.g. &tmpDockerfile) to indicate that the referenced Dockerfile is a temporary one that we created that should be deleted after it is read. Then we know for sure we're not mucking with the user's files at all.

@tonistiigi
Copy link
Member Author

@duglin When content trust is used we add a digest to every FROM instruction if needed, before uploading the Dockerfile. We don't rename the file while doing so.

@duglin
Copy link
Contributor

duglin commented Mar 7, 2017

that's interesting - is this during a docker build so that it knows which file is the real Dockerfile?

@tonistiigi
Copy link
Member Author

@duglin @cpuguy83 I have updated to use the random name and .dockerignore. I generalized the tar converter method as well so the same method can be more easily used for dct and plugin create.

Copy link
Contributor

Choose a reason for hiding this comment

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

I know its really really unlikely, but to avoid a flaky situation, can you just check to make sure there isn't a file with this name already in the build context? And if so, try again.

Copy link
Member Author

Choose a reason for hiding this comment

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

In 99% of the places we don't check things like this and it would make the code really complicated with multiple passes to achieve this. I increased the size if you are actually worried about the collisions.

dsheets and others added 2 commits April 5, 2017 19:42
Heavily based on implementation by David Sheets

Signed-off-by: David Sheets <[email protected]>
Signed-off-by: Tonis Tiigi <[email protected]>
@dnephin
Copy link
Member

dnephin commented Apr 5, 2017

I've rebased and pushed a couple commits to address these comments.

I updated the tests for ReplaceFileTarWrapper to use table testing, and added a case for appending to a file.

return nil, nil, err
}
} else {
b.WriteString("\n.dockerignore")

Choose a reason for hiding this comment

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

In this case, content is nil, so this will be the first entry in the file, and we shouldn't need to begin with a \n.

Choose a reason for hiding this comment

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

...but we should probably include a \n at the end in case someone tries to look at the file from the context. I think @duglin requested this in a comment on an earlier version.

Copy link
Member

Choose a reason for hiding this comment

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

Outside of this if/else there is a write that adds the trailing newline. So I think that's covered.

I'll remove the first \n, you're right it's not necessary.

Improve test coverage of ReplaceFileTarWrapper()

Signed-off-by: Daniel Nephin <[email protected]>
@dnephin
Copy link
Member

dnephin commented Apr 6, 2017

Ok, added the comment, and also fixed a failing test. content was being passed as an empty reader instead of nil. This case is now also caught by the unit tests, and the comment for TarModifierFunc mentions that content will be nil when the file doesn't exist.

@aaronlehmann
Copy link

LGTM

@tonistiigi
Copy link
Member Author

LGTM for the latest updates

Copy link
Member

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

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

LGTM 🦁
Just one small comment 👼

"archive/tar"
"bytes"
"fmt"
"github.com/docker/docker/pkg/testutil/assert"
Copy link
Member

Choose a reason for hiding this comment

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

nit but this import is not in the right place 😛

@vdemeester vdemeester merged commit 778e32a into moby:master Apr 10, 2017
@GordonTheTurtle GordonTheTurtle added this to the 17.05.0 milestone Apr 10, 2017
dnephin pushed a commit to dnephin/docker that referenced this pull request Apr 17, 2017
build: accept -f - to read Dockerfile from stdin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: docker build read Dockerfile from stdin