bug: COPY does not take /. (slash-dot) into account
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 10.3k
- Forks
- 1.5k
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 48
Description
Relates to https://github.com/moby/moby/pull/38599
note: this is the same behavior as the classic builder, so we should discuss if we can change this without introducing a breaking change π
I think there's a bug in the copy behavior (both in classic builder, and in buildkit); it's come up a few times, and matching with the docker cp documentation;
SRC_PATHspecifies a directory:
DEST_PATHdoes not exist
DEST_PATHis created as a directory and the contents of the source directory are copied into this directoryDEST_PATHexists and is a file
- Error condition: cannot copy a directory to a file
DEST_PATHexists and is a directory
SRC_PATHdoes not end with/.(that is: slash followed by dot)
- the source directory is copied into this directory
SRC_PATHdoes end with/.(that is: slash followed by dot)
- the content of the source directory is copied into this directory
So without the trailing /., this line should result in dir itself being copied to /existingdir/dir; similar to cp:
Without trailing /.;
docker run --rm --workdir=/test alpine sh -c 'apk add --no-cache --quiet tree && mkdir -p src/dir/subdir dest/existingdir && touch src/dir/subdir/nestedfile && cp -R src/dir dest/existingdir && cd /test/dest && tree'
.
βββ existingdir
βββ dir
βββ subdir
βββ nestedfile
3 directories, 1 file
With trailing /.;
docker run --rm --workdir=/test alpine sh -c 'apk add --no-cache --quiet tree && mkdir -p src/dir/subdir dest/existingdir && touch src/dir/subdir/nestedfile && cp -R src/dir/. dest/existingdir && cd /test/dest && tree'
.
βββ existingdir
βββ subdir
βββ nestedfile
2 directories, 1 file
In a Dockerfile; without trailing /.;
DOCKER_BUILDKIT=1 docker build -<<EOF
FROM alpine AS source
RUN mkdir -p /dir/subdir && touch /dir/subdir/nestedfile
FROM alpine AS no_slash_dot
WORKDIR /dest
RUN apk add --no-cache --quiet tree
RUN mkdir existingdir
COPY --from=source /dir existingdir
RUN tree; exit 1
EOF
Produces;
.
βββ existingdir
βββ subdir
βββ nestedfile
2 directories, 1 file
And with;
DOCKER_BUILDKIT=1 docker build -<<EOF
FROM alpine AS source
RUN mkdir -p /dir/subdir && touch /dir/subdir/nestedfile
FROM alpine AS slash_dot
WORKDIR /dest
RUN apk add --no-cache --quiet tree
RUN mkdir existingdir
COPY --from=source /dir/. existingdir
RUN tree; exit 1
EOF
Produces the same;
.
βββ existingdir
βββ subdir
βββ nestedfile
2 directories, 1 file
The behavior should match the cp -R result
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up β it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing Dockerfile COPY handling in BuildKit and compare it with the documented docker cp behavior and the classic builder. Reproduce both COPY --from cases with and without a trailing '/.' and add regression coverage where the existing COPY tests belong. Done means the results match cp -R, subject to resolving the noted compatibility concern.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100