diff --git a/requirements.txt b/requirements.txt
index f7083ec..b40b9ac 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,6 +14,6 @@ virtualenv-api>=2.1.16
 virtualenv
 twine>=1.9.1
 pluggage>=0.0.4
-dockerstache>=0.0.13
+dockerstache>=0.0.14
 requests-toolbelt>=0.8.0
 tox>=2.7.0
diff --git a/src/cirrus/docker.py b/src/cirrus/docker.py
index cb491f0..0b74c2d 100644
--- a/src/cirrus/docker.py
+++ b/src/cirrus/docker.py
@@ -218,12 +218,17 @@ def _docker_build(path, tags, base_tag, build_helper):
     command.append(path)
     LOGGER.info("Executing docker build command: {}".format(' '.join(command)))
 
-    try:
-        stdout = subprocess.check_output(command)
-    except subprocess.CalledProcessError as ex:
-        LOGGER.error(ex.output)
-        raise
-    LOGGER.info(stdout)
+    p = subprocess.Popen(
+        command,
+        stdout=sys.stdout,
+        stderr=sys.stderr
+        )
+    status = p.wait()
+    if status:
+        msg = "docker build exited non-zero!"
+        LOGGER.error(msg)
+        raise RuntimeError(msg)
+
     image = find_image_id(base_tag)
     LOGGER.info("Image ID: {}".format(image))
 

More readable/streaming output from docker-image build
The `git cirrus docker-image build` is really useful.  It would be maybe even more useful if we could get at least one of these:

* more readable output; if there is an error in the output it's very hard to read
* streaming so that we can watch it scroll past the screen rather than wait until the end
diff --git a/tests/unit/cirrus/docker_test.py b/tests/unit/cirrus/docker_test.py
index a98b684..f6a11e3 100644
--- a/tests/unit/cirrus/docker_test.py
+++ b/tests/unit/cirrus/docker_test.py
@@ -29,6 +29,7 @@ class DockerFunctionTests(unittest.TestCase):
         self.mock_popen.return_value = self.mock_popen
         self.mock_popen.communicate = mock.Mock()
         self.mock_popen.communicate.return_value = ('STDOUT', 'STDERR')
+        self.mock_popen.wait = mock.Mock(return_value=0)
 
         self.opts = mock.Mock()
         self.opts.login = False
@@ -65,10 +66,17 @@ class DockerFunctionTests(unittest.TestCase):
     def test_docker_build(self):
         """test straight docker build call"""
         dckr.docker_build(self.opts, self.config)
-        self.failUnless(self.mock_check_output.called)
-        self.mock_check_output.assert_has_calls(
+        self.failUnless(self.mock_popen.wait.called)
+        self.mock_popen.assert_has_calls(
             mock.call(
-                ['docker', 'build', '-t', 'unittesting/unittesting:latest', '-t', 'unittesting/unittesting:1.2.3', 'vm/docker_image']
+                [
+                    'docker', 'build', '-t',
+                    'unittesting/unittesting:latest', '-t',
+                    'unittesting/unittesting:1.2.3',
+                    'vm/docker_image'
+                ],
+                stderr=mock.ANY,
+                stdout=mock.ANY
             )
         )
 
@@ -77,15 +85,17 @@ class DockerFunctionTests(unittest.TestCase):
         self.opts.build_arg = {"OPTION1": "VALUE1"}
         self.opts.no_cache = False
         dckr.docker_build(self.opts, self.config)
-        self.failUnless(self.mock_check_output.called)
-        self.mock_check_output.assert_has_calls(
+        self.failUnless(self.mock_popen.wait.called)
+        self.mock_popen.assert_has_calls(
             mock.call(
                 [
                     'docker', 'build',
                     '-t', 'unittesting/unittesting:latest',
                     '-t', 'unittesting/unittesting:1.2.3',
                     '--build-arg', 'OPTION1=VALUE1',
-                    'vm/docker_image']
+                    'vm/docker_image'],
+                stderr=mock.ANY,
+                stdout=mock.ANY
             )
         )
 
@@ -94,8 +104,8 @@ class DockerFunctionTests(unittest.TestCase):
         self.opts.build_arg = {"OPTION1": "VALUE1"}
         self.opts.no_cache = True
         dckr.docker_build(self.opts, self.config)
-        self.failUnless(self.mock_check_output.called)
-        self.mock_check_output.assert_has_calls(
+        self.failUnless(self.mock_popen.wait.called)
+        self.mock_popen.assert_has_calls(
             mock.call(
                 [
                     'docker', 'build',
@@ -103,15 +113,17 @@ class DockerFunctionTests(unittest.TestCase):
                     '-t', 'unittesting/unittesting:1.2.3',
                     '--no-cache',
                     '--build-arg', 'OPTION1=VALUE1',
-                    'vm/docker_image']
+                    'vm/docker_image'],
+                stderr=mock.ANY,
+                stdout=mock.ANY
             )
         )
 
     def test_docker_build_addl_repos(self):
         self.config['docker']['additional_repos'] = "repo1:8080, repo2:8080 "
         dckr.docker_build(self.opts, self.config)
-        self.failUnless(self.mock_check_output.called)
-        self.mock_check_output.assert_has_calls(
+        self.failUnless(self.mock_popen.wait.called)
+        self.mock_popen.assert_has_calls(
             mock.call(
                 [
                     'docker', 'build',
@@ -121,7 +133,9 @@ class DockerFunctionTests(unittest.TestCase):
                     '-t', 'repo1:8080/unittesting:latest',
                     '-t', 'repo2:8080/unittesting:1.2.3',
                     '-t', 'repo2:8080/unittesting:latest',
-                    'vm/docker_image']
+                    'vm/docker_image'],
+                stderr=mock.ANY,
+                stdout=mock.ANY
             )
         )
 
@@ -146,9 +160,16 @@ class DockerFunctionTests(unittest.TestCase):
                 output='vm/docker_image', context=None, defaults=None, input='template', extend_context=mock.ANY
             )
         )
-        self.mock_check_output.assert_has_calls(
+        self.mock_popen.assert_has_calls(
             mock.call(
-                ['docker', 'build', '-t', 'unittesting/unittesting:latest', '-t', 'unittesting/unittesting:1.2.3', 'vm/docker_image']
+                [
+                    'docker', 'build', '-t',
+                    'unittesting/unittesting:latest', '-t',
+                    'unittesting/unittesting:1.2.3',
+                    'vm/docker_image'
+                ],
+                stderr=mock.ANY,
+                stdout=mock.ANY
             )
         )
 
@@ -167,9 +188,20 @@ class DockerFunctionTests(unittest.TestCase):
         self.failUnless(self.mock_check_output.called)
         self.mock_check_output.assert_has_calls(
             [
-                mock.call(['docker', 'login', '-u', 'steve', '-p', 'st3v3R0X', 'unittesting']),
-                mock.call(['docker', 'build', '-t', 'unittesting/unittesting:latest', '-t', 'unittesting/unittesting:1.2.3', 'vm/docker_image'])
-            ]
+                mock.call(
+                    ['docker', 'login', '-u', 'steve', '-p', 'st3v3R0X', 'unittesting'],
+                )
+            ])
+        self.mock_popen.assert_has_calls(
+            mock.call(
+                [
+                    'docker', 'build', '-t',
+                    'unittesting/unittesting:latest', '-t',
+                    'unittesting/unittesting:1.2.3', 'vm/docker_image'
+                ],
+                stderr=mock.ANY,
+                stdout=mock.ANY
+            )
         )
 
     def test_docker_push(self):

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
arrow==1.2.3
astroid==2.11.7
attrs==22.2.0
bleach==4.1.0
certifi==2021.5.30
cffi==1.15.1
charset-normalizer==2.0.12
chevron==0.14.0
-e git+https://github.com/evansde77/cirrus.git@e745a2056779cb2fbc12c02d9fe2f57de6764d14#egg=cirrus_cli
colorama==0.4.5
cryptography==40.0.2
dill==0.3.4
distlib==0.3.9
dockerstache==0.0.17
docutils==0.18.1
filelock==3.4.1
gitdb==4.0.9
GitPython==3.1.18
idna==3.10
importlib-metadata==4.8.3
importlib-resources==5.4.0
iniconfig==1.1.1
invoke==2.2.0
isort==5.10.1
jeepney==0.7.1
keyring==23.4.1
lazy-object-proxy==1.7.1
mccabe==0.7.0
mock==1.0.1
nose==1.3.7
packaging==21.3
pep8==1.7.1
pkginfo==1.10.0
platformdirs==2.4.0
pluggage==0.0.4
pluggy==1.0.0
py==1.11.0
PyChef==0.2.3
pycparser==2.21
Pygments==2.14.0
pylint==2.13.9
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
readme-renderer==34.0
requests==2.27.1
requests-toolbelt==1.0.0
rfc3986==1.5.0
SecretStorage==3.3.3
six==1.17.0
smmap==5.0.0
toml==0.10.2
tomli==1.2.3
tox==3.28.0
tqdm==4.64.1
twine==3.8.0
typed-ast==1.5.5
typing_extensions==4.1.1
urllib3==1.26.20
virtualenv==20.17.1
virtualenv-api==2.1.18
webencodings==0.5.1
wrapt==1.16.0
zipp==3.6.0

name: cirrus
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - argparse==1.4.0
      - arrow==1.2.3
      - astroid==2.11.7
      - attrs==22.2.0
      - bleach==4.1.0
      - cffi==1.15.1
      - charset-normalizer==2.0.12
      - chevron==0.14.0
      - colorama==0.4.5
      - cryptography==40.0.2
      - dill==0.3.4
      - distlib==0.3.9
      - dockerstache==0.0.17
      - docutils==0.18.1
      - filelock==3.4.1
      - gitdb==4.0.9
      - gitpython==3.1.18
      - idna==3.10
      - importlib-metadata==4.8.3
      - importlib-resources==5.4.0
      - iniconfig==1.1.1
      - invoke==2.2.0
      - isort==5.10.1
      - jeepney==0.7.1
      - keyring==23.4.1
      - lazy-object-proxy==1.7.1
      - mccabe==0.7.0
      - mock==1.0.1
      - nose==1.3.7
      - packaging==21.3
      - pep8==1.7.1
      - pkginfo==1.10.0
      - platformdirs==2.4.0
      - pluggage==0.0.4
      - pluggy==1.0.0
      - py==1.11.0
      - pychef==0.2.3
      - pycparser==2.21
      - pygments==2.14.0
      - pylint==2.13.9
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - readme-renderer==34.0
      - requests==2.27.1
      - requests-toolbelt==1.0.0
      - rfc3986==1.5.0
      - secretstorage==3.3.3
      - six==1.17.0
      - smmap==5.0.0
      - toml==0.10.2
      - tomli==1.2.3
      - tox==3.28.0
      - tqdm==4.64.1
      - twine==3.8.0
      - typed-ast==1.5.5
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - virtualenv==20.17.1
      - virtualenv-api==2.1.18
      - webencodings==0.5.1
      - wrapt==1.16.0
      - zipp==3.6.0
prefix: /opt/conda/envs/cirrus

tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_build tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_build_addl_repos tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_build_args tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_build_login tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_build_no_cache tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_build_template
tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_build_tag_opts tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_connection tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_connection_error tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_connection_success tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_push tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_push_addl tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_push_latest tests/unit/cirrus/docker_test.py::DockerFunctionTests::test_docker_push_login tests/unit/cirrus/docker_test.py::DockerUtilTest::test_get_docker_version tests/unit/cirrus/docker_test.py::DockerUtilTest::test_get_docker_version_error tests/unit/cirrus/docker_test.py::DockerUtilTest::test_is_docker_version_installed tests/unit/cirrus/docker_test.py::DockerUtilTest::test_match_docker_version_error
src/cirrus/docker.py requirements.txt
src/cirrus/docker.py requirements.txt