Add .dockerignore support

Fixes #2224

Docker-DCO-1.1-Signed-off-by: Travis Cline <travis.cline@gmail.com> (github: tmc)
This commit is contained in:
Travis Cline 2014-02-15 10:38:48 -08:00 committed by Victor Vieux
parent 111ab125b9
commit 9189db3aff
4 changed files with 101 additions and 1 deletions

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
bundles
.gopath

View file

@ -13,6 +13,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path" "path"
"path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
@ -163,7 +164,24 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
if err = utils.ValidateContextDirectory(root); err != nil { if err = utils.ValidateContextDirectory(root); err != nil {
return fmt.Errorf("Error checking context is accessible: '%s'. Please check permissions and try again.", err) return fmt.Errorf("Error checking context is accessible: '%s'. Please check permissions and try again.", err)
} }
context, err = archive.Tar(root, archive.Uncompressed) options := &archive.TarOptions{
Compression: archive.Uncompressed,
}
ignoreFile := path.Join(root, ".dockerignore")
if ignore, err := ioutil.ReadFile(ignoreFile); err == nil {
for _, pattern := range strings.Split(string(ignore), "\n") {
ok, err := filepath.Match(pattern, "Dockerfile")
if err != nil {
utils.Errorf("Bad .dockerignore pattern: '%s', error: %s", pattern, err)
continue
}
if ok {
return fmt.Errorf("Dockerfile was excluded by .dockerignore pattern '%s'", pattern)
}
options.Excludes = append(options.Excludes, pattern)
}
}
context, err = archive.TarWithOptions(root, options)
} }
var body io.Reader var body io.Reader
// Setup an upload progress bar // Setup an upload progress bar

View file

@ -215,6 +215,12 @@ temporary directory on your local host, and then this is sent to the
Docker daemon as the context. This way, your local user credentials and Docker daemon as the context. This way, your local user credentials and
vpn's etc can be used to access private repositories. vpn's etc can be used to access private repositories.
If a file named ``.dockerignore`` exists in the root of ``PATH`` then it is
interpreted as a newline-separated list of exclusion patterns. Exclusion
patterns match files or directories relative to ``PATH`` that will be excluded
from the context. Globbing is done using Go's
[filepath.Match](http://golang.org/pkg/path/filepath#Match) rules.
See also: See also:
[*Dockerfile Reference*](/reference/builder/#dockerbuilder). [*Dockerfile Reference*](/reference/builder/#dockerbuilder).
@ -266,6 +272,30 @@ If you wish to keep the intermediate containers after the build is
complete, you must use `--rm=false`. This does not complete, you must use `--rm=false`. This does not
affect the build cache. affect the build cache.
$ docker build .
Uploading context 18.829 MB
Uploading context
Step 0 : FROM busybox
---> 769b9341d937
Step 1 : CMD echo Hello World
---> Using cache
---> 99cc1ad10469
Successfully built 99cc1ad10469
$ echo ".git" > .dockerignore
$ docker build .
Uploading context 6.76 MB
Uploading context
Step 0 : FROM busybox
---> 769b9341d937
Step 1 : CMD echo Hello World
---> Using cache
---> 99cc1ad10469
Successfully built 99cc1ad10469
This example shows the use of the ``.dockerignore`` file to exclude the ``.git``
directory the context. Its effect can be seen in the changed size of the
uploaded context.
$ sudo docker build -t vieux/apache:2.0 . $ sudo docker build -t vieux/apache:2.0 .
This will build like the previous example, but it will then tag the This will build like the previous example, but it will then tag the

View file

@ -1514,3 +1514,53 @@ docker.com>"
logDone("build - validate escaping whitespace") logDone("build - validate escaping whitespace")
} }
func TestDockerignore(t *testing.T) {
name := "testbuilddockerignore"
defer deleteImages(name)
dockerfile := `
FROM busybox
ADD . /bla
RUN [[ -f /bla/src/x.go ]]
RUN [[ -f /bla/Makefile ]]
RUN [[ ! -e /bla/src/_vendor ]]
RUN [[ ! -e /bla/.gitignore ]]
RUN [[ ! -e /bla/README.md ]]
RUN [[ ! -e /bla/.git ]]`
ctx, err := fakeContext(dockerfile, map[string]string{
"Makefile": "all:",
".git/HEAD": "ref: foo",
"src/x.go": "package main",
"src/_vendor/v.go": "package main",
".gitignore": "",
"README.md": "readme",
".dockerignore": ".git\npkg\n.gitignore\nsrc/_vendor\n*.md",
})
defer ctx.Close()
if err != nil {
t.Fatal(err)
}
if _, err := buildImageFromContext(name, ctx, true); err != nil {
t.Fatal(err)
}
logDone("build - test .dockerignore")
}
func TestDockerignoringDockerfile(t *testing.T) {
name := "testbuilddockerignoredockerfile"
defer deleteImages(name)
dockerfile := `
FROM scratch`
ctx, err := fakeContext(dockerfile, map[string]string{
"Dockerfile": "FROM scratch",
".dockerignore": "Dockerfile\n",
})
defer ctx.Close()
if err != nil {
t.Fatal(err)
}
if _, err = buildImageFromContext(name, ctx, true); err == nil {
t.Fatalf("Didn't get expected error from ignoring Dockerfile")
}
logDone("build - test .dockerignore of Dockerfile")
}