From f21f9f856e9d5af23521f131799028c2e67c04ed Mon Sep 17 00:00:00 2001 From: Doug Davis Date: Fri, 12 Dec 2014 10:32:11 -0800 Subject: [PATCH] Allow for relative paths on ADD/COPY Moved Tianon's PR from: https://github.com/docker/docker/pull/7870 on top of the latest code Closes: #3936 Signed-off-by: Andrew Page Signed-off-by: Doug Davis --- builder/dispatchers.go | 11 +++---- builder/internals.go | 12 +++++++ docs/man/Dockerfile.5.md | 20 +++++++++--- docs/man/docker-build.1.md | 10 +++--- docs/sources/reference/builder.md | 12 ++++--- integration-cli/docker_cli_build_test.go | 40 ++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 20 deletions(-) diff --git a/builder/dispatchers.go b/builder/dispatchers.go index eb9485fa79..9fb44fc452 100644 --- a/builder/dispatchers.go +++ b/builder/dispatchers.go @@ -172,15 +172,12 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str workdir := args[0] - if workdir[0] == '/' { - b.Config.WorkingDir = workdir - } else { - if b.Config.WorkingDir == "" { - b.Config.WorkingDir = "/" - } - b.Config.WorkingDir = filepath.Join(b.Config.WorkingDir, workdir) + if !filepath.IsAbs(workdir) { + workdir = filepath.Join("/", b.Config.WorkingDir, workdir) } + b.Config.WorkingDir = workdir + return b.commit("", b.Config.Cmd, fmt.Sprintf("WORKDIR %v", workdir)) } diff --git a/builder/internals.go b/builder/internals.go index c1fd617a56..d30a7da810 100644 --- a/builder/internals.go +++ b/builder/internals.go @@ -217,6 +217,18 @@ func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath stri } origPath = strings.TrimPrefix(origPath, "./") + // Twiddle the destPath when its a relative path - meaning, make it + // relative to the WORKINGDIR + if !filepath.IsAbs(destPath) { + hasSlash := strings.HasSuffix(destPath, "/") + destPath = filepath.Join("/", b.Config.WorkingDir, destPath) + + // Make sure we preserve any trailing slash + if hasSlash { + destPath += "/" + } + } + // In the remote/URL case, download it and gen its hashcode if urlutil.IsURL(origPath) { if !allowRemote { diff --git a/docs/man/Dockerfile.5.md b/docs/man/Dockerfile.5.md index 4104dc2321..0114f30ba7 100644 --- a/docs/man/Dockerfile.5.md +++ b/docs/man/Dockerfile.5.md @@ -132,12 +132,22 @@ or **ADD** --**ADD ... ** The ADD instruction copies new files, directories - or remote file URLs to the filesystem of the container at path . + or remote file URLs to the filesystem of the container at path . Mutliple resources may be specified but if they are files or directories - then they must be relative to the source directory that is being built - (the context of the build). is the absolute path to - which the source is copied inside the target container. All new files and - directories are created with mode 0755, with uid and gid 0. + then they must be relative to the source directory that is being built + (the context of the build). The is the absolute path, or path relative + to `WORKDIR`, into which the source is copied inside the target container. + All new files and directories are created with mode 0755 and with the uid + and gid of 0. + +**COPY** + --**COPY ** The COPY instruction copies new files from and + adds them to the filesystem of the container at path . The must be + the path to a file or directory relative to the source directory that is + being built (the context of the build) or a remote file URL. The `` is an + absolute path, or a path relative to `WORKDIR`, into which the source will + be copied inside the target container. All new files and directories are + created with mode 0755 and with the uid and gid of 0. **ENTRYPOINT** --**ENTRYPOINT** has two forms: ENTRYPOINT ["executable", "param1", "param2"] diff --git a/docs/man/docker-build.1.md b/docs/man/docker-build.1.md index 67d7343af3..3fed996406 100644 --- a/docs/man/docker-build.1.md +++ b/docs/man/docker-build.1.md @@ -65,10 +65,12 @@ directory called httpd may be used to store Dockerfiles for Apache web server images. It is also a good practice to add the files required for the image to the -sub-directory. These files will then be specified with the `ADD` instruction -in the Dockerfile. Note: If you include a tar file (a good practice!), then -Docker will automatically extract the contents of the tar file -specified within the `ADD` instruction into the specified target. +sub-directory. These files will then be specified with the `COPY` or `ADD` +instructions in the `Dockerfile`. + +Note: If you include a tar file (a good practice), then Docker will +automatically extract the contents of the tar file specified within the `ADD` +instruction into the specified target. ## Building an image and naming that image diff --git a/docs/sources/reference/builder.md b/docs/sources/reference/builder.md index adc308c9d6..e8b2b0696a 100644 --- a/docs/sources/reference/builder.md +++ b/docs/sources/reference/builder.md @@ -397,8 +397,10 @@ For most command line uses this should act as expected, for example: ADD hom* /mydir/ # adds all files starting with "hom" ADD hom?.txt /mydir/ # ? is replaced with any single character -The `` is the absolute path to which the source will be copied inside the -destination container. +The `` is an absolute path, or a path relative to `WORKDIR`, into which +the source will be copied inside the destination container. + + ADD test aDir/ # adds "test" to `WORKDIR`/aDir/ All new files and directories are created with a UID and GID of 0. @@ -494,8 +496,10 @@ For most command line uses this should act as expected, for example: COPY hom* /mydir/ # adds all files starting with "hom" COPY hom?.txt /mydir/ # ? is replaced with any single character -The `` is the absolute path to which the source will be copied inside the -destination container. +The `` is an absolute path, or a path relative to `WORKDIR`, into which +the source will be copied inside the destination container. + + COPY test aDir/ # adds "test" to `WORKDIR`/aDir/ All new files and directories are created with a UID and GID of 0. diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index ccd0b6d3e7..0d527119cb 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -1829,6 +1829,46 @@ func TestBuildWorkdirWithEnvVariables(t *testing.T) { logDone("build - workdir with env variables") } +func TestBuildRelativeCopy(t *testing.T) { + name := "testbuildrelativecopy" + defer deleteImages(name) + dockerfile := ` + FROM busybox + WORKDIR /test1 + WORKDIR test2 + RUN [ "$PWD" = '/test1/test2' ] + COPY foo ./ + RUN [ "$(cat /test1/test2/foo)" = 'hello' ] + ADD foo ./bar/baz + RUN [ "$(cat /test1/test2/bar/baz)" = 'hello' ] + COPY foo ./bar/baz2 + RUN [ "$(cat /test1/test2/bar/baz2)" = 'hello' ] + WORKDIR .. + COPY foo ./ + RUN [ "$(cat /test1/foo)" = 'hello' ] + COPY foo /test3/ + RUN [ "$(cat /test3/foo)" = 'hello' ] + WORKDIR /test4 + COPY . . + RUN [ "$(cat /test4/foo)" = 'hello' ] + WORKDIR /test5/test6 + COPY foo ../ + RUN [ "$(cat /test5/foo)" = 'hello' ] + ` + ctx, err := fakeContext(dockerfile, map[string]string{ + "foo": "hello", + }) + defer ctx.Close() + if err != nil { + t.Fatal(err) + } + _, err = buildImageFromContext(name, ctx, false) + if err != nil { + t.Fatal(err) + } + logDone("build - relative copy/add") +} + func TestBuildEnv(t *testing.T) { name := "testbuildenv" expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"