I've been stuck on this for awhile. I would like docker to ignore a particular directory when building an image, because my user account does not have permissions to read that directory. I cannot move it, so that's not an alternative.
This is the structure of my project. docker/data
is the directory that I do not have permissions to read, and docker/node-express.dockerfile
is the image I'm trying to build.
Running docker build --no-cache --tag node-express --file ./docker/node-express.dockerfile .
in the root directory outputs the error
error checking context: 'can't stat '/home/anthony/Repositories/Anthony-Monterrosa/aws-postgres-node-stack/docker/data''.
After this error and a bit of googling I learned about .dockerignore
files, and made one in the root directory. The following is the file's text.
docker/data
I ran the command again but got an identical error. A bit more googling and I found out about image-specific .dockerignore
files, so I set DOCKER_BUILDKIT
to 1
, created docker/node-express.dockerfile.dockerignore
with the following content
data
docker/data
(I am not sure how relative paths work with image-specific .dockerignores, so I added both). Ran the command again, but still with the same error.
So, I don't seem to have ignores working correctly with either .dockerignore
file, or both. What am I missing here?
The error is:
error checking context: 'can't stat '/home/anthony/Repositories/Anthony-Monterrosa/aws-postgres-node-stack/docker/data''.
So looks there is some operation before .dockerignore
effect.
As there is no context content in your docker
folder, I suggest you just add docker
in .dockerignore
.
This way, although still error, but the build will continue like next:
shubuntu1@shubuntu1:~/trial2020/trial$ docker build -t abcd:1 -f docker/Dockerfile .
ERRO[0000] Tar: Can't stat file /home/shubuntu1/trial2020/trial to tar: open
/home/shubuntu1/trial2020/trial/docker/data: permission denied
Sending build context to Docker daemon 3.072kB
Step 1/1 : FROM ubuntu:18.04
---> 3556258649b2
Successfully built 3556258649b2
Successfully tagged abcd:1
UPDATE why according to your comments:
You may want to have a look for docker-ce source code, build.go & context.go:
build.go:
if err := build.ValidateContextDirectory(contextDir, excludes); err != nil {
return errors.Errorf("error checking context: '%s'.", err)
}
context.go:
func ValidateContextDirectory(srcPath string, excludes []string) error {
contextRoot, err := getContextRoot(srcPath)
if err != nil {
return err
}
pm, err := fileutils.NewPatternMatcher(excludes)
if err != nil {
return err
}
return filepath.Walk(contextRoot, func(filePath string, f os.FileInfo, err error) error {
if err != nil {
if os.IsPermission(err) {
return errors.Errorf("can't stat '%s'", filePath)
}
if os.IsNotExist(err) {
return errors.Errorf("file ('%s') not found or excluded by .dockerignore", filePath)
}
return err
}
// skip this directory/file if it's not in the path, it won't get added to the context
if relFilePath, err := filepath.Rel(contextRoot, filePath); err != nil {
return err
} else if skip, err := filepathMatches(pm, relFilePath); err != nil {
return err
} else if skip {
if f.IsDir() {
return filepath.SkipDir
}
return nil
}
......
})
}
Before docker daemon tar the build context, it will first try to validate the context directory:
docker/data
in .dockerignore
:
It will use Walk
to ergodic all things under docker
, when it comes to docker/data
, next code finally make the build exit, so you
did not get image generated:
if os.IsPermission(err) {
return errors.Errorf("can't stat '%s'", filePath)
}
docker
in .dockerignore
:
Same as above, difference is next code will effect when comes to the match docker
in .dockerignore
:
return filepath.SkipDir
This will make the Walk
ignore the subfolders of docker
, then docker/data
no chance to be ergodic, so no permission error there.
The ERRO[0000] Tar: Can't stat file
comes from other later steps which won't exit the image build.