dockerfile: add COPY --link for copy via merging layers#2596
dockerfile: add COPY --link for copy via merging layers#2596tonistiigi merged 2 commits intomoby:masterfrom
Conversation
|
Pushed frontend for testing. To setup buildx with mergeop support: The progress will show multiple rows for |
sipsma
left a comment
There was a problem hiding this comment.
In terms of the flag name, I think --link is fine. I like --rebase too, which is sort of suggestive of how it works in terms of structuring layers, but that might only appeal to me because I know the internal details of how it works.
| d.state = d.state.File(a, fileOpt...) | ||
| if cfg.opt.llbCaps.Supports(pb.CapMergeOp) == nil && cfg.link && cfg.chmod == "" { | ||
| mergeOpt := append(fileOpt, llb.WithCustomName(prefixCommand(d, "LINK "+name, d.prefixPlatform, &platform, env))) | ||
| d.state = llb.Merge([]llb.State{d.state, llb.Scratch().File(a, fileOpt...)}, mergeOpt...) |
There was a problem hiding this comment.
nit: If it's easy to implement, it seems like if the user is copying from another stage (i.e. not a local ref) and isn't using any special flags, then the case of COPY --link --from=foo / / could skip the file op and just merge directly.
This wouldn't be needed if we manage to get the more optimized implementation where all copies are directly hardlinked into merges before the next release, but not sure how plausible that is as it seemed fairly complicated when we last discussed.
There was a problem hiding this comment.
Thanks, though I just thought of something that's worth considering. I remembered that this behavior implies that any deletions present in the layers of the source of the link will be applied on top of the new base, which is different than the behavior you get with copies where all the source layers are squashed and deletions are discarded.
I can't think of a single realistic Dockerfile use case where this would matter, but did want to bring it up in case you think this somewhat divergent behavior might matter.
There was a problem hiding this comment.
I'm not sure about the whiteouts but thought about another case. This currently would mess up the history array in the image as history array will only expect that one layer was generated by the command. Possibly something can be done with adding some markers to overcome this (not quite sure) but I think I will revert this part for now.
There was a problem hiding this comment.
Okay cool sgtm, the use case for this optimization was pretty niche anyways so doesn't hurt much to save it for the future.
709b5ca to
b784ea0
Compare
|
Question; would this option only apply to If that's the case, should it be an option on |
|
Ignore me; I was commenting before reading (let me get back to that) |
frontend/dockerfile/docs/syntax.md
Outdated
|
|
||
| To use this flag set Dockerfile version to at least `1.4`. | ||
|
|
||
| ``` |
There was a problem hiding this comment.
can you add dockerfile code-hints to the blocks that show Dockerfile examples? (so that highlighting will work if we publish it)
| COPY /foo /bar | ||
| ``` | ||
|
|
||
| and merging all the layers of both images together. |
There was a problem hiding this comment.
merging all the layers
Does that mean that this produces a single layer (alpine + copy) ? Won't that result in the alpine layer no longer being shared? (I recall we tried to avoid that when implementing docker build --squash, where we kept the base-layer out of the squashing to allow it to still be shared).
FROM alpine
COPY --link /foo /barThis somewhat implies that;
FROM alpine
COPY --link /foo /bar
COPY --link /bar /bazWould result in a single layer (alpine + copy + copy) (is that correct?)
There was a problem hiding this comment.
No, there is no flatten. Merging layers means that if you merge 2 layers with 3 then result is 5 layers. Layers are immutable blobs in the registry.
There was a problem hiding this comment.
Side note, I'm working on some user docs for the lower-level MergeOp. We can consider updating these Dockerfile docs to mention those ones once I'm done, which might help clarify questions like this that have to do with finer-grain details.
Enables smarter file copy logic using the mergeop implementation. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
b784ea0 to
8441d0a
Compare
crazy-max
left a comment
There was a problem hiding this comment.
SGTM, also looking forward for typical use cases in our docs https://github.com/moby/buildkit/pull/2596/files#r803941857 to avoid confusion with layers aggregation.
Still WIP, but pushed the draft here if you want to take a look now: #2633 |
|
|
||
| #### Incompatibilities with `--link=false` | ||
|
|
||
| When using `--link` the `COPY/ADD` commands are not allowed to read any files from the previous state. This means that if in previous state the destination directory was a path that contained a symlink, `COPY/ADD` can not follow it. In the final image the destination path created with `--link` will always be a path containing only directories. |
There was a problem hiding this comment.
EDIT: ignore comment, i'm completely wrong
Need also mention that you can no longer merge directories from a previous layer:
$ mkdir dir_to_be_merged ; echo foo > dir_to_be_merged/foo
$ cat > Dockerfile <<EOF
FROM alpine
RUN mkdir /dir && echo bar > /dir/bar
COPY dir_to_be_merged /dir
RUN test "$(cat /dir/bar)" = bar
EOF
$ docker build . # should work without COPY --link=false and fail with COPY --link
|
My main concern is that anything named
|
|
@tonistiigi Hi, just to confirm...
Thank you for the information! |
|
Usually, This; docker --version
Docker version 20.10.14, build a224086Is "implicitly" the same as an explicit: docker --version=true
Docker version 20.10.14, build a224086Same for "don't pass the docker
# (no --version set prints usage)
docker --version=false
# (same - prints usage)That said, it's possible that (perhaps!) these options can at some point be filled in through a build-arg, in which case being able to explicitly specify the FROM foobar
ARG USE_LINK=false
COPY --link=$USE_LINK .... |
|
@thaJeztah Thank you very much for clarifying. I work on a Dockerfile linter so I just wanted to confirm the different syntax variants that are valid. Have a nice day! |
replaces #2423
fixes #2414
Enables smarter file copy logic using the mergeop implementation. See docs in the PR contents.
Not 100% sure about the flag name.
Currently on top of #2513 for the progress groups support.
TODO/follow-up:
--chown(currently same as with--link=false)