Fixes #2224
Docker-DCO-1.1-Signed-off-by: Travis Cline <travis.cline@gmail.com> (github: tmc)
| ... | ... |
@@ -13,6 +13,7 @@ import ( |
| 13 | 13 |
"os" |
| 14 | 14 |
"os/exec" |
| 15 | 15 |
"path" |
| 16 |
+ "path/filepath" |
|
| 16 | 17 |
"runtime" |
| 17 | 18 |
"strconv" |
| 18 | 19 |
"strings" |
| ... | ... |
@@ -163,7 +164,24 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
|
| 163 | 163 |
if err = utils.ValidateContextDirectory(root); err != nil {
|
| 164 | 164 |
return fmt.Errorf("Error checking context is accessible: '%s'. Please check permissions and try again.", err)
|
| 165 | 165 |
} |
| 166 |
- context, err = archive.Tar(root, archive.Uncompressed) |
|
| 166 |
+ options := &archive.TarOptions{
|
|
| 167 |
+ Compression: archive.Uncompressed, |
|
| 168 |
+ } |
|
| 169 |
+ ignoreFile := path.Join(root, ".dockerignore") |
|
| 170 |
+ if ignore, err := ioutil.ReadFile(ignoreFile); err == nil {
|
|
| 171 |
+ for _, pattern := range strings.Split(string(ignore), "\n") {
|
|
| 172 |
+ ok, err := filepath.Match(pattern, "Dockerfile") |
|
| 173 |
+ if err != nil {
|
|
| 174 |
+ utils.Errorf("Bad .dockerignore pattern: '%s', error: %s", pattern, err)
|
|
| 175 |
+ continue |
|
| 176 |
+ } |
|
| 177 |
+ if ok {
|
|
| 178 |
+ return fmt.Errorf("Dockerfile was excluded by .dockerignore pattern '%s'", pattern)
|
|
| 179 |
+ } |
|
| 180 |
+ options.Excludes = append(options.Excludes, pattern) |
|
| 181 |
+ } |
|
| 182 |
+ } |
|
| 183 |
+ context, err = archive.TarWithOptions(root, options) |
|
| 167 | 184 |
} |
| 168 | 185 |
var body io.Reader |
| 169 | 186 |
// Setup an upload progress bar |
| ... | ... |
@@ -215,6 +215,12 @@ temporary directory on your local host, and then this is sent to the |
| 215 | 215 |
Docker daemon as the context. This way, your local user credentials and |
| 216 | 216 |
vpn's etc can be used to access private repositories. |
| 217 | 217 |
|
| 218 |
+If a file named ``.dockerignore`` exists in the root of ``PATH`` then it is |
|
| 219 |
+interpreted as a newline-separated list of exclusion patterns. Exclusion |
|
| 220 |
+patterns match files or directories relative to ``PATH`` that will be excluded |
|
| 221 |
+from the context. Globbing is done using Go's |
|
| 222 |
+[filepath.Match](http://golang.org/pkg/path/filepath#Match) rules. |
|
| 223 |
+ |
|
| 218 | 224 |
See also: |
| 219 | 225 |
|
| 220 | 226 |
[*Dockerfile Reference*](/reference/builder/#dockerbuilder). |
| ... | ... |
@@ -266,6 +272,30 @@ If you wish to keep the intermediate containers after the build is |
| 266 | 266 |
complete, you must use `--rm=false`. This does not |
| 267 | 267 |
affect the build cache. |
| 268 | 268 |
|
| 269 |
+ $ docker build . |
|
| 270 |
+ Uploading context 18.829 MB |
|
| 271 |
+ Uploading context |
|
| 272 |
+ Step 0 : FROM busybox |
|
| 273 |
+ ---> 769b9341d937 |
|
| 274 |
+ Step 1 : CMD echo Hello World |
|
| 275 |
+ ---> Using cache |
|
| 276 |
+ ---> 99cc1ad10469 |
|
| 277 |
+ Successfully built 99cc1ad10469 |
|
| 278 |
+ $ echo ".git" > .dockerignore |
|
| 279 |
+ $ docker build . |
|
| 280 |
+ Uploading context 6.76 MB |
|
| 281 |
+ Uploading context |
|
| 282 |
+ Step 0 : FROM busybox |
|
| 283 |
+ ---> 769b9341d937 |
|
| 284 |
+ Step 1 : CMD echo Hello World |
|
| 285 |
+ ---> Using cache |
|
| 286 |
+ ---> 99cc1ad10469 |
|
| 287 |
+ Successfully built 99cc1ad10469 |
|
| 288 |
+ |
|
| 289 |
+This example shows the use of the ``.dockerignore`` file to exclude the ``.git`` |
|
| 290 |
+directory the context. Its effect can be seen in the changed size of the |
|
| 291 |
+uploaded context. |
|
| 292 |
+ |
|
| 269 | 293 |
$ sudo docker build -t vieux/apache:2.0 . |
| 270 | 294 |
|
| 271 | 295 |
This will build like the previous example, but it will then tag the |
| ... | ... |
@@ -1514,3 +1514,53 @@ docker.com>" |
| 1514 | 1514 |
|
| 1515 | 1515 |
logDone("build - validate escaping whitespace")
|
| 1516 | 1516 |
} |
| 1517 |
+ |
|
| 1518 |
+func TestDockerignore(t *testing.T) {
|
|
| 1519 |
+ name := "testbuilddockerignore" |
|
| 1520 |
+ defer deleteImages(name) |
|
| 1521 |
+ dockerfile := ` |
|
| 1522 |
+ FROM busybox |
|
| 1523 |
+ ADD . /bla |
|
| 1524 |
+ RUN [[ -f /bla/src/x.go ]] |
|
| 1525 |
+ RUN [[ -f /bla/Makefile ]] |
|
| 1526 |
+ RUN [[ ! -e /bla/src/_vendor ]] |
|
| 1527 |
+ RUN [[ ! -e /bla/.gitignore ]] |
|
| 1528 |
+ RUN [[ ! -e /bla/README.md ]] |
|
| 1529 |
+ RUN [[ ! -e /bla/.git ]]` |
|
| 1530 |
+ ctx, err := fakeContext(dockerfile, map[string]string{
|
|
| 1531 |
+ "Makefile": "all:", |
|
| 1532 |
+ ".git/HEAD": "ref: foo", |
|
| 1533 |
+ "src/x.go": "package main", |
|
| 1534 |
+ "src/_vendor/v.go": "package main", |
|
| 1535 |
+ ".gitignore": "", |
|
| 1536 |
+ "README.md": "readme", |
|
| 1537 |
+ ".dockerignore": ".git\npkg\n.gitignore\nsrc/_vendor\n*.md", |
|
| 1538 |
+ }) |
|
| 1539 |
+ defer ctx.Close() |
|
| 1540 |
+ if err != nil {
|
|
| 1541 |
+ t.Fatal(err) |
|
| 1542 |
+ } |
|
| 1543 |
+ if _, err := buildImageFromContext(name, ctx, true); err != nil {
|
|
| 1544 |
+ t.Fatal(err) |
|
| 1545 |
+ } |
|
| 1546 |
+ logDone("build - test .dockerignore")
|
|
| 1547 |
+} |
|
| 1548 |
+ |
|
| 1549 |
+func TestDockerignoringDockerfile(t *testing.T) {
|
|
| 1550 |
+ name := "testbuilddockerignoredockerfile" |
|
| 1551 |
+ defer deleteImages(name) |
|
| 1552 |
+ dockerfile := ` |
|
| 1553 |
+ FROM scratch` |
|
| 1554 |
+ ctx, err := fakeContext(dockerfile, map[string]string{
|
|
| 1555 |
+ "Dockerfile": "FROM scratch", |
|
| 1556 |
+ ".dockerignore": "Dockerfile\n", |
|
| 1557 |
+ }) |
|
| 1558 |
+ defer ctx.Close() |
|
| 1559 |
+ if err != nil {
|
|
| 1560 |
+ t.Fatal(err) |
|
| 1561 |
+ } |
|
| 1562 |
+ if _, err = buildImageFromContext(name, ctx, true); err == nil {
|
|
| 1563 |
+ t.Fatalf("Didn't get expected error from ignoring Dockerfile")
|
|
| 1564 |
+ } |
|
| 1565 |
+ logDone("build - test .dockerignore of Dockerfile")
|
|
| 1566 |
+} |