Repository: docker/docker-py

Issue:
ERROR: Cannot locate specified Dockerfile
I'm not sure if this is a Docker Compose bug or docker-py bug, but this used to work:

`docker-compose.yml`:
```yaml
version: '3.5'

services:
  php:
    build:
      context: .
      dockerfile: ./docker/php.Dockerfile
```

but now the `./` prefix is causing:
```
ERROR: Cannot locate specified Dockerfile: ./docker/php.Dockerfile
```

I have to change it to `dockerfile: docker/php.Dockerfile` to get it to work.

--

docker-py version: 3.1.1

Python 3.6.4

`docker version`:
```
Client:
 Version:	18.02.0-ce
 API version:	1.36
 Go version:	go1.9.4
 Git commit:	fc4de447b5
 Built:	Tue Feb 13 15:28:01 2018
 OS/Arch:	linux/amd64
 Experimental:	false
 Orchestrator:	swarm

Server:
 Engine:
  Version:	18.02.0-ce
  API version:	1.36 (minimum version 1.12)
  Go version:	go1.9.4
  Git commit:	fc4de447b5
  Built:	Tue Feb 13 15:28:34 2018
  OS/Arch:	linux/amd64
  Experimental:	false
```

OS: Manjaro Linux 17.1.6


Discussion:
Thanks for the report! 

Resolving patch:
diff --git a/docker/utils/build.py b/docker/utils/build.py
--- a/docker/utils/build.py
+++ b/docker/utils/build.py
@@ -31,18 +31,21 @@ def exclude_paths(root, patterns, dockerfile=None):
     if dockerfile is None:
         dockerfile = 'Dockerfile'
 
+    def split_path(p):
+        return [pt for pt in re.split(_SEP, p) if pt and pt != '.']
+
     def normalize(p):
         # Leading and trailing slashes are not relevant. Yes,
         # "foo.py/" must exclude the "foo.py" regular file. "."
         # components are not relevant either, even if the whole
         # pattern is only ".", as the Docker reference states: "For
         # historical reasons, the pattern . is ignored."
-        split = [pt for pt in re.split(_SEP, p) if pt and pt != '.']
         # ".." component must be cleared with the potential previous
         # component, regardless of whether it exists: "A preprocessing
         # step [...]  eliminates . and .. elements using Go's
         # filepath.".
         i = 0
+        split = split_path(p)
         while i < len(split):
             if split[i] == '..':
                 del split[i]
@@ -62,7 +65,7 @@ def normalize(p):
         # Exclude empty patterns such as "." or the empty string.
         filter(lambda p: p[1], patterns),
         # Always include the Dockerfile and .dockerignore
-        [(True, dockerfile.split('/')), (True, ['.dockerignore'])]))))
+        [(True, split_path(dockerfile)), (True, ['.dockerignore'])]))))
     return set(walk(root, patterns))
 
 


Test patch:
diff --git a/tests/unit/utils_test.py b/tests/unit/utils_test.py
--- a/tests/unit/utils_test.py
+++ b/tests/unit/utils_test.py
@@ -698,6 +698,11 @@ def test_exclude_custom_dockerfile(self):
             ['*'], dockerfile='foo/Dockerfile3'
         ) == convert_paths(set(['foo/Dockerfile3', '.dockerignore']))
 
+        # https://github.com/docker/docker-py/issues/1956
+        assert self.exclude(
+            ['*'], dockerfile='./foo/Dockerfile3'
+        ) == convert_paths(set(['foo/Dockerfile3', '.dockerignore']))
+
     def test_exclude_dockerfile_child(self):
         includes = self.exclude(['foo/'], dockerfile='foo/Dockerfile3')
         assert convert_path('foo/Dockerfile3') in includes