moby / buildkit

concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit
https://github.com/moby/moby/issues/34227
Apache License 2.0
7.86k stars 1.09k forks source link

BuildKit COPY different behavior than normal mode #1667

Open sdhoward opened 3 years ago

sdhoward commented 3 years ago

Hi,

I'm using Docker for Mac with engine 19.03.12. I have the following build directory layout, where source1 and source2 are empty files:

$ ls -1
Dockerfile
source1
source2

Given the following Dockerfile, different results are seen when building with BuildKit vs. normal mode.

FROM alpine:3.12

WORKDIR /foo
COPY source1 source2 .
RUN ls

Normal mode throws the expected error:

$ docker build --no-cache .
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM alpine:3.12
 ---> a24bb4013296
Step 2/4 : WORKDIR /foo
 ---> Running in bc18da17dfc4
Removing intermediate container bc18da17dfc4
 ---> 39d182c1ed6b
Step 3/4 : COPY source1 source2 .
When using COPY with more than one source file, the destination must be a directory and end with a /

BuildKit unexpectedly allows the unusual Dockerfile syntax:

$ DOCKER_BUILDKIT=1 docker build --no-cache --progress=plain .
#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 103B done
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/alpine:3.12
#3 DONE 0.0s

#4 [1/4] FROM docker.io/library/alpine:3.12
#4 CACHED

#6 [internal] load build context
#6 transferring context: 50B done
#6 DONE 0.0s

#5 [2/4] WORKDIR /foo
#5 DONE 0.0s

#7 [3/4] COPY source1 source2 .
#7 DONE 0.1s

#8 [4/4] RUN ls
#8 0.213 source1
#8 0.213 source2
#8 DONE 0.3s

#9 exporting to image
#9 exporting layers 0.0s done
#9 writing image sha256:7ea5dea1acdba8ec57eae7e98873e91c66c7f0aa5ffff623d96cde58f76a24c8 done
#9 DONE 0.0s

Shouldn't the two building systems parse the dockerfile in the same way? This blog post implies that "all the patterns" should work with both. If this isn't a bug, there should be some document that shows the differences.

There doesn't appear to be any mention of a change to COPY syntax in the experimental doc either.

tonistiigi commented 3 years ago

Requiring / in the path is a limitation of old implementation that shouldn't be needed anymore. Don't see any functional difference. As your output shows the result was correct and your files were copied to the working directory.

sdhoward commented 3 years ago

This behavior should only be enabled with that experimental syntax directive.

The difference is that BuildKit is enabling people to write Dockerfiles that are neither portable nor compatible.

Alternatively, I should be able to add a legacy syntax directive that forces BuildKit to follow the standard rules.

tonistiigi commented 3 years ago

Buildkit is compatible with old builder (except some edge cases where we are not replicating buggy behavior). Old builder is not compatible with buildkit. New features are added to Dockerfile and will not be backported to old builder. Eg. variables in chown, or --chmod, or multiple dockerignore are only in BuildKit.

thaJeztah commented 3 years ago

Requiring / in the path is a limitation of old implementation that shouldn't be needed anymore. Don't see any functional difference. As your output shows the result was correct and your files were copied to the working directory.

I just opened a ticket about this (didn't find this one when I opened), but I do think there's still reasons for the / to be used; see the description/reproduction steps in https://github.com/moby/buildkit/issues/1853