Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 5, 2025
When working with Docker, the docker build command helps us create container images based on the instructions defined in a Dockerfile. Typically, during the build process, Docker prints each command it executes as well as its corresponding output to the terminal. With this feedback, we can monitor if each step executes as expected.
However, we may encounter situations where the expected output isn’t visible, making it difficult to verify whether each step runs properly. As a consequence, debugging the Dockerfile can become frustrating.
In this tutorial, we’ll explore why docker build fails to show output from commands and how to ensure that these outputs are displayed correctly.
To demonstrate, let’s consider a working directory with a simple Dockerfile:
$ cat Dockerfile
FROM node:18
RUN echo "Hello World"
RUN apt-get update -y && apt-get install -y postgresql-client
RUN psql --version
In this Dockerfile:
When we run the docker build . command, we might expect to see the output of all RUN commands. However, we may only get logs indicating the commands were executed, without seeing the actual output:
$ docker build .
...
=> [2/4] RUN echo "Hello World" 3.5s
=> [3/4] RUN apt-get update -y && apt-get install -y postgresql-client 30.1s
=> [4/4] RUN psql --version 2.4s
The above output can complicate the process of verifying the success of each step.
Here, let’s discuss why docker build may not show output from commands.
Docker uses multiple layers to build container images, caching previous successful steps. Thus, if a command was previously executed and cached, Docker reuses the cached layer without rerunning the command. For this reason, we may not see the command output since Docker skips this step entirely.
Additionally, the Dockerfile may contain some commands that don’t print output unless we explicitly configure them to do so. For instance, the RUN apt-get update -y && apt-get install -y postgresql-client command takes care of updating the package lists and installing the PostgreSQL client. However, not all package managers display progress information or provide detailed logs by default. As a result, during the Docker build process, some parts of the installation process may not produce visible results in the terminal.
Docker’s logging system collects and displays the output of each build step. However, the output may not appear immediately because both Docker and certain command-line tools implement buffering mechanisms. To clarify, buffering is common in CLI tools to optimize performance.
For instance, the psql –version command is meant to print the installed version of the PostgreSQL client. When run in a regular terminal, it prints the result immediately. However, during a Docker build, the output may be buffered by Docker or the command itself, causing it to appear only after the step completes. Additionally, psql –version executes quickly and only provides a minimal output (the version number). For this reason, we may wrongly assume the command never ran.
To ensure the output appears immediately during the build process, we can redirect it and force Docker to print the command output in real-time rather than waiting for the step to complete.
Let’s discuss a few approaches we can utilize to ensure that output appears correctly.
We can use the –no-cache flag when building the image to guarantee that commands run every time:
$ docker build --no-cache .
This command forces Docker to run each step from scratch instead of using cached layers. Although this ensures the visibility of the output, it may slow down the build process, sometimes needlessly.
In cases where commands execute quickly and provide minimal output, Docker may fail to display the output immediately. To solve this, we can explicitly redirect output to ensure it appears in real-time.
To demonstrate, let’s modify RUN psql –version:
RUN psql --version | tee /dev/stderr
Here, the tee command reads from standard input and writes to both standard output and standard error (/dev/stderr). By redirecting the output to /dev/stderr, we ensure that Docker’s logging system prints the output immediately.
Another approach we can utilize to ensure real-time output display is by using unbuffer, a command from the expect package. Since many command-line tools buffer their output to improve performance, the display of logs during a Docker build may be delayed. To avoid this, we can attempt to prevent buffering.
Before we use unbuffer, we install the expect package since most Docker base images don’t include it by default. So, let’s install the package and modify the appropriate commands to include unbuffer:
RUN apt-get update -y && apt-get install -y postgresql-client expect
RUN unbuffer psql --version
This addition ensures that the psql –version command output is not held in a buffer. Therefore, we can apply this approach to commands experiencing delayed output when run inside a Docker build.
In this approach, we append && echo “Done!”:
RUN psql --version && echo "Done!"
Above, we ensure that the command provides a visible output, in this case, Done!, even if the expected output is buffered or suppressed.
Let’s note that this approach simply ensures that at least some output is available to help in debugging. It may not visualize all relevant data, depending on the situation.
In this article, we explored possible reasons why docker build may fail to show output from commands.
So, when we run docker build, we expect to see output from every RUN command in the Dockerfile. However, due to the Docker caching mechanism, how package managers handle logs, and how the Docker logging system holds output, some results may not be immediately visible.
To address this, we disabled build caching using the –no-cache flag, redirected output using tee /dev/stderr, and implemented unbuffer to display output in real-time. Additionally, we explored a temporary workaround using the echo command to ensure at least an output is visible, even if it doesn’t fully resolve the buffering issue. Now, we should be able to more easily debug a Dockerfile.