Keywords: Docker Build | BuildKit | Command Output
Abstract: This technical paper provides a comprehensive analysis of the missing command output issue during Docker build processes, focusing on BuildKit engine behavior and configuration options. Through detailed code examples and configuration explanations, it demonstrates the usage of --progress=plain parameter, BUILDKIT_PROGRESS environment variable, and --no-cache option for controlling build output. The paper also discusses reverting to traditional build engine and offers best practice recommendations for real-world application scenarios.
Problem Analysis
During Docker image building, users frequently encounter situations where command outputs become invisible. From the provided Dockerfile example:
FROM node:12.18.0
RUN echo "hello world"
RUN psql --version
When executing docker build ., although the build process completes normally, users cannot see the standard output from echo and psql --version commands. This phenomenon is particularly noticeable in Docker version 19.03.13, where build output only shows step execution times:
=> [7/18] RUN echo "hello world" 0.9s
=> [8/18] RUN psql --version 17.1s
Root Cause: BuildKit Engine
The core issue lies with Docker's default BuildKit build engine. BuildKit is Docker's next-generation build engine designed to provide better performance, security, and scalability. Compared to traditional build engines, BuildKit employs different strategies for output handling.
BuildKit's default output mode is auto, where:
- The system automatically detects terminal type and optimizes output format
- Non-cached build steps only display execution time summaries
- Command standard output and standard error are suppressed
- Cache-hit steps display
CACHEDmarkers
Detailed Solutions
Using --progress Parameter
The most direct solution is using the --progress=plain parameter:
docker build --progress=plain .
This parameter forces BuildKit to output in plain text mode, completely displaying command outputs from all build steps. To better understand its working mechanism, we can create a test script:
#!/bin/bash
# Simulating output behavior during build process
echo "Starting build process..."
echo "Step 1: Installing dependencies"
apt-get update && apt-get install -y postgresql-client
echo "Step 2: Verifying installation"
psql --version
echo "Build completed"
Environment Variable Configuration
To avoid specifying parameters for each build, environment variables can be set:
export BUILDKIT_PROGRESS=plain
docker build .
This configuration approach is particularly suitable for development environments, maintaining detailed build output continuously. The scope of environment variables depends on the setup method:
- Set in current terminal session: Only effective for current session
- Set in shell configuration files: Effective for all new sessions
- Set in Docker configuration files: System-level configuration
Cache Handling Strategy
When build steps are already cached, outputs cannot be seen even with --progress=plain. In such cases, the --no-cache parameter should be combined:
docker build --progress=plain --no-cache .
This method forces re-execution of all build steps, suitable for debugging and problem investigation scenarios. In actual development, we can flexibly choose based on requirements:
# View output of specific steps only
docker build --progress=plain --target=specific-stage .
# Combine with other debugging parameters
docker build --progress=plain --no-cache --pull .
Traditional Build Engine Fallback
For certain specific scenarios, reverting to the traditional Docker build engine might be necessary:
DOCKER_BUILDKIT=0 docker build .
Or set persistent environment variables:
export DOCKER_BUILDKIT=0
docker build .
Characteristics of traditional build engine include:
- Line-by-line build process output
- Real-time display of command execution results
- Simpler caching mechanism
- Potentially lower performance in some cases
Practical Application Scenarios
Debugging Complex Build Processes
When handling complex multi-stage builds, detailed output information is crucial. Consider the following scenario:
FROM node:12.18.0 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM node:12.18.0-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
Using --progress=plain allows clear viewing of build outputs from each stage, facilitating problem localization.
Continuous Integration Environment
In CI/CD pipelines, the completeness of build output directly affects problem investigation efficiency. It's recommended to explicitly set in CI configuration:
# GitHub Actions example
- name: Build Docker image
run: |
docker build \
--progress=plain \
--no-cache \
-t ${{ env.IMAGE_NAME }} .
Best Practice Recommendations
Based on practical project experience, we recommend the following configuration strategies:
- Development Environment: Set
BUILDKIT_PROGRESS=plainenvironment variable to maintain detailed build output - Production Environment: Use default
automode to reduce log output volume - Debugging Scenarios: Combine
--progress=plain --no-cachefor comprehensive problem investigation - Team Collaboration: Clearly specify build output configuration requirements in project documentation
Additionally, it's recommended to add appropriate log outputs in Dockerfile for easier problem diagnosis:
RUN echo "Starting PostgreSQL client installation..." && \
apt-get update && \
apt-get install -y postgresql-client && \
echo "Installation completed, version information:" && \
psql --version
Conclusion
The missing Docker build output issue primarily stems from BuildKit engine's default behavior configuration. Through reasonable use of --progress parameters, environment variables, and cache control options, build output detail levels can be flexibly adjusted. In actual projects, appropriate configuration solutions should be selected based on specific requirements, balancing output information completeness and build efficiency.