Allow for relative paths on ADD/COPY
| ... | ... |
@@ -172,15 +172,12 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str |
| 172 | 172 |
|
| 173 | 173 |
workdir := args[0] |
| 174 | 174 |
|
| 175 |
- if workdir[0] == '/' {
|
|
| 176 |
- b.Config.WorkingDir = workdir |
|
| 177 |
- } else {
|
|
| 178 |
- if b.Config.WorkingDir == "" {
|
|
| 179 |
- b.Config.WorkingDir = "/" |
|
| 180 |
- } |
|
| 181 |
- b.Config.WorkingDir = filepath.Join(b.Config.WorkingDir, workdir) |
|
| 175 |
+ if !filepath.IsAbs(workdir) {
|
|
| 176 |
+ workdir = filepath.Join("/", b.Config.WorkingDir, workdir)
|
|
| 182 | 177 |
} |
| 183 | 178 |
|
| 179 |
+ b.Config.WorkingDir = workdir |
|
| 180 |
+ |
|
| 184 | 181 |
return b.commit("", b.Config.Cmd, fmt.Sprintf("WORKDIR %v", workdir))
|
| 185 | 182 |
} |
| 186 | 183 |
|
| ... | ... |
@@ -217,6 +217,18 @@ func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath stri |
| 217 | 217 |
} |
| 218 | 218 |
origPath = strings.TrimPrefix(origPath, "./") |
| 219 | 219 |
|
| 220 |
+ // Twiddle the destPath when its a relative path - meaning, make it |
|
| 221 |
+ // relative to the WORKINGDIR |
|
| 222 |
+ if !filepath.IsAbs(destPath) {
|
|
| 223 |
+ hasSlash := strings.HasSuffix(destPath, "/") |
|
| 224 |
+ destPath = filepath.Join("/", b.Config.WorkingDir, destPath)
|
|
| 225 |
+ |
|
| 226 |
+ // Make sure we preserve any trailing slash |
|
| 227 |
+ if hasSlash {
|
|
| 228 |
+ destPath += "/" |
|
| 229 |
+ } |
|
| 230 |
+ } |
|
| 231 |
+ |
|
| 220 | 232 |
// In the remote/URL case, download it and gen its hashcode |
| 221 | 233 |
if urlutil.IsURL(origPath) {
|
| 222 | 234 |
if !allowRemote {
|
| ... | ... |
@@ -132,12 +132,22 @@ or |
| 132 | 132 |
|
| 133 | 133 |
**ADD** |
| 134 | 134 |
--**ADD <src>... <dest>** The ADD instruction copies new files, directories |
| 135 |
- or remote file URLs to the filesystem of the container at path <dest>. |
|
| 135 |
+ or remote file URLs to the filesystem of the container at path <dest>. |
|
| 136 | 136 |
Mutliple <src> resources may be specified but if they are files or directories |
| 137 |
- then they must be relative to the source directory that is being built |
|
| 138 |
- (the context of the build). <dest> is the absolute path to |
|
| 139 |
- which the source is copied inside the target container. All new files and |
|
| 140 |
- directories are created with mode 0755, with uid and gid 0. |
|
| 137 |
+ then they must be relative to the source directory that is being built |
|
| 138 |
+ (the context of the build). The <dest> is the absolute path, or path relative |
|
| 139 |
+ to `WORKDIR`, into which the source is copied inside the target container. |
|
| 140 |
+ All new files and directories are created with mode 0755 and with the uid |
|
| 141 |
+ and gid of 0. |
|
| 142 |
+ |
|
| 143 |
+**COPY** |
|
| 144 |
+ --**COPY <src> <dest>** The COPY instruction copies new files from <src> and |
|
| 145 |
+ adds them to the filesystem of the container at path <dest>. The <src> must be |
|
| 146 |
+ the path to a file or directory relative to the source directory that is |
|
| 147 |
+ being built (the context of the build) or a remote file URL. The `<dest>` is an |
|
| 148 |
+ absolute path, or a path relative to `WORKDIR`, into which the source will |
|
| 149 |
+ be copied inside the target container. All new files and directories are |
|
| 150 |
+ created with mode 0755 and with the uid and gid of 0. |
|
| 141 | 151 |
|
| 142 | 152 |
**ENTRYPOINT** |
| 143 | 153 |
--**ENTRYPOINT** has two forms: ENTRYPOINT ["executable", "param1", "param2"] |
| ... | ... |
@@ -65,10 +65,12 @@ directory called httpd may be used to store Dockerfiles for Apache web |
| 65 | 65 |
server images. |
| 66 | 66 |
|
| 67 | 67 |
It is also a good practice to add the files required for the image to the |
| 68 |
-sub-directory. These files will then be specified with the `ADD` instruction |
|
| 69 |
-in the Dockerfile. Note: If you include a tar file (a good practice!), then |
|
| 70 |
-Docker will automatically extract the contents of the tar file |
|
| 71 |
-specified within the `ADD` instruction into the specified target. |
|
| 68 |
+sub-directory. These files will then be specified with the `COPY` or `ADD` |
|
| 69 |
+instructions in the `Dockerfile`. |
|
| 70 |
+ |
|
| 71 |
+Note: If you include a tar file (a good practice), then Docker will |
|
| 72 |
+automatically extract the contents of the tar file specified within the `ADD` |
|
| 73 |
+instruction into the specified target. |
|
| 72 | 74 |
|
| 73 | 75 |
## Building an image and naming that image |
| 74 | 76 |
|
| ... | ... |
@@ -397,8 +397,10 @@ For most command line uses this should act as expected, for example: |
| 397 | 397 |
ADD hom* /mydir/ # adds all files starting with "hom" |
| 398 | 398 |
ADD hom?.txt /mydir/ # ? is replaced with any single character |
| 399 | 399 |
|
| 400 |
-The `<dest>` is the absolute path to which the source will be copied inside the |
|
| 401 |
-destination container. |
|
| 400 |
+The `<dest>` is an absolute path, or a path relative to `WORKDIR`, into which |
|
| 401 |
+the source will be copied inside the destination container. |
|
| 402 |
+ |
|
| 403 |
+ ADD test aDir/ # adds "test" to `WORKDIR`/aDir/ |
|
| 402 | 404 |
|
| 403 | 405 |
All new files and directories are created with a UID and GID of 0. |
| 404 | 406 |
|
| ... | ... |
@@ -494,8 +496,10 @@ For most command line uses this should act as expected, for example: |
| 494 | 494 |
COPY hom* /mydir/ # adds all files starting with "hom" |
| 495 | 495 |
COPY hom?.txt /mydir/ # ? is replaced with any single character |
| 496 | 496 |
|
| 497 |
-The `<dest>` is the absolute path to which the source will be copied inside the |
|
| 498 |
-destination container. |
|
| 497 |
+The `<dest>` is an absolute path, or a path relative to `WORKDIR`, into which |
|
| 498 |
+the source will be copied inside the destination container. |
|
| 499 |
+ |
|
| 500 |
+ COPY test aDir/ # adds "test" to `WORKDIR`/aDir/ |
|
| 499 | 501 |
|
| 500 | 502 |
All new files and directories are created with a UID and GID of 0. |
| 501 | 503 |
|
| ... | ... |
@@ -1829,6 +1829,46 @@ func TestBuildWorkdirWithEnvVariables(t *testing.T) {
|
| 1829 | 1829 |
logDone("build - workdir with env variables")
|
| 1830 | 1830 |
} |
| 1831 | 1831 |
|
| 1832 |
+func TestBuildRelativeCopy(t *testing.T) {
|
|
| 1833 |
+ name := "testbuildrelativecopy" |
|
| 1834 |
+ defer deleteImages(name) |
|
| 1835 |
+ dockerfile := ` |
|
| 1836 |
+ FROM busybox |
|
| 1837 |
+ WORKDIR /test1 |
|
| 1838 |
+ WORKDIR test2 |
|
| 1839 |
+ RUN [ "$PWD" = '/test1/test2' ] |
|
| 1840 |
+ COPY foo ./ |
|
| 1841 |
+ RUN [ "$(cat /test1/test2/foo)" = 'hello' ] |
|
| 1842 |
+ ADD foo ./bar/baz |
|
| 1843 |
+ RUN [ "$(cat /test1/test2/bar/baz)" = 'hello' ] |
|
| 1844 |
+ COPY foo ./bar/baz2 |
|
| 1845 |
+ RUN [ "$(cat /test1/test2/bar/baz2)" = 'hello' ] |
|
| 1846 |
+ WORKDIR .. |
|
| 1847 |
+ COPY foo ./ |
|
| 1848 |
+ RUN [ "$(cat /test1/foo)" = 'hello' ] |
|
| 1849 |
+ COPY foo /test3/ |
|
| 1850 |
+ RUN [ "$(cat /test3/foo)" = 'hello' ] |
|
| 1851 |
+ WORKDIR /test4 |
|
| 1852 |
+ COPY . . |
|
| 1853 |
+ RUN [ "$(cat /test4/foo)" = 'hello' ] |
|
| 1854 |
+ WORKDIR /test5/test6 |
|
| 1855 |
+ COPY foo ../ |
|
| 1856 |
+ RUN [ "$(cat /test5/foo)" = 'hello' ] |
|
| 1857 |
+ ` |
|
| 1858 |
+ ctx, err := fakeContext(dockerfile, map[string]string{
|
|
| 1859 |
+ "foo": "hello", |
|
| 1860 |
+ }) |
|
| 1861 |
+ defer ctx.Close() |
|
| 1862 |
+ if err != nil {
|
|
| 1863 |
+ t.Fatal(err) |
|
| 1864 |
+ } |
|
| 1865 |
+ _, err = buildImageFromContext(name, ctx, false) |
|
| 1866 |
+ if err != nil {
|
|
| 1867 |
+ t.Fatal(err) |
|
| 1868 |
+ } |
|
| 1869 |
+ logDone("build - relative copy/add")
|
|
| 1870 |
+} |
|
| 1871 |
+ |
|
| 1832 | 1872 |
func TestBuildEnv(t *testing.T) {
|
| 1833 | 1873 |
name := "testbuildenv" |
| 1834 | 1874 |
expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]" |