Repository: docker/docker-py

Issue:
images.build failing on container build output
The ImageCollection.build() method parses the `docker build` output to extract the name of the image being built by looking for the string "Successfully built {sha256}".  Some commands in a Dockerfile can also produce this string causing the build() method to return early with an incorrect image name.

Example output from a `RUN pip install cffi` command:
```
 ...
Building wheels for collected packages: cffi, pycparser
  Running setup.py bdist_wheel for cffi
  Stored in directory: /root/.cache/pip/wheels/ea/df/5c/7d11cd4eec7b94be3b0ec4ed0076e0f38846a22c7200576149
  Running setup.py bdist_wheel for pycparser
  Stored in directory: /root/.cache/pip/wheels/bc/07/7e/cd81c0b23417ebaed9eb2584c00bd539871d5309a7a2324953
Successfully built cffi pycparser
...
```

A partial fix is to make the regex used to search for the string more restrictive by adding start and end anchors.  This can still result in some false positives.
A more complete fix only checks the last line of output for the "Success..." string.
PR in progress.

```
docker==2.3.0
docker-pycreds==0.2.1
Python 2.7.5
Client:
 Version:         1.12.6
 API version:     1.24
 Package version: docker-common-1.12.6-16.el7.x86_64
 Go version:      go1.7.4
 Git commit:      3a094bd/1.12.6
 Built:           Tue Mar 21 13:30:59 2017
 OS/Arch:         linux/amd64

Server:
 Version:         17.03.1-ce
 API version:     1.27
 Package version: 
 Go version:      go1.7.5
 Git commit:      c6d412e
 Built:           Fri Mar 24 00:00:50 2017
 OS/Arch:         linux/amd64
```


Discussion:

Resolving patch:
diff --git a/docker/models/images.py b/docker/models/images.py
--- a/docker/models/images.py
+++ b/docker/models/images.py
@@ -169,19 +169,20 @@ def build(self, **kwargs):
         if isinstance(resp, six.string_types):
             return self.get(resp)
         last_event = None
+        image_id = None
         for chunk in json_stream(resp):
             if 'error' in chunk:
                 raise BuildError(chunk['error'])
             if 'stream' in chunk:
                 match = re.search(
-                    r'(Successfully built |sha256:)([0-9a-f]+)',
+                    r'(^Successfully built |sha256:)([0-9a-f]+)$',
                     chunk['stream']
                 )
                 if match:
                     image_id = match.group(2)
-                    return self.get(image_id)
             last_event = chunk
-
+        if image_id:
+            return self.get(image_id)
         raise BuildError(last_event or 'Unknown')
 
     def get(self, name):


Test patch:
diff --git a/tests/integration/models_images_test.py b/tests/integration/models_images_test.py
--- a/tests/integration/models_images_test.py
+++ b/tests/integration/models_images_test.py
@@ -39,6 +39,17 @@ def test_build_with_multiple_success(self):
         self.tmp_imgs.append(image.id)
         assert client.containers.run(image) == b"hello world\n"
 
+    def test_build_with_success_build_output(self):
+        client = docker.from_env(version=TEST_API_VERSION)
+        image = client.images.build(
+            tag='dup-txt-tag', fileobj=io.BytesIO(
+                "FROM alpine\n"
+                "CMD echo Successfully built abcd1234".encode('ascii')
+            )
+        )
+        self.tmp_imgs.append(image.id)
+        assert client.containers.run(image) == b"Successfully built abcd1234\n"
+
     def test_list(self):
         client = docker.from_env(version=TEST_API_VERSION)
         image = client.images.pull('alpine:latest')