Keywords: Docker | ARG instruction | ENV instruction | build configuration | runtime configuration | PHP-FPM container
Abstract: This article provides an in-depth exploration of the fundamental differences between ARG and ENV instructions in Dockerfile, using PHP-FPM container construction as a case study. It analyzes best practices for build-time parameter passing and runtime environment configuration, detailing the essential distinctions between ARG for build-stage customization and ENV for container runtime settings, while offering hybrid strategies that combine both approaches for flexible configuration management.
Core Concepts of Docker Build Configuration
In Docker containerized deployment, configuration management is a critical aspect of building efficient and maintainable images. Dockerfile provides two primary configuration mechanisms: ARG (build arguments) and ENV (environment variables). Understanding the fundamental differences between these two is essential for designing flexible containerization solutions.
Semantic Differences Between ARG and ENV
According to the Docker official documentation, the ARG instruction defines variables that are passed during the build stage, valid only during the docker build process. Users can specify argument values at build time using the --build-arg <varname>=<value> flag. For example:
FROM ubuntu:latest
ARG VERSION=1.0
RUN echo "Building version ${VERSION}"
During build, the default value can be overridden with docker build --build-arg VERSION=2.0 ..
In contrast, environment variables set using the ENV instruction persist into the final generated image and remain available during container runtime. This means that variables defined with ENV affect not only the build process but also the container's runtime behavior. For example:
FROM php:7.4-fpm
ENV APP_ENV=production
CMD ["php-fpm"]
When running the container, environment variables can be overridden with docker run -e APP_ENV=development.
Case Study: PHP-FPM Container Configuration
Consider a PHP-FPM container construction scenario where extensions need to be dynamically enabled or disabled based on user requirements. The original implementation used multiple ENV variables as switch flags:
ENV INSTALL_XDEBUG="false" \
INSTALL_MONGO="false" \
INSTALL_REDIS="false"
These environment variables are detected in the container startup script to determine whether to install corresponding extensions. While this approach works, when managing a large number of configurable items, it results in numerous ENV definitions in the Dockerfile that serve only control logic purposes.
Selection Strategy: Build-Time vs Runtime Configuration
The choice between ARG and ENV depends on the temporal requirements of the configuration:
- Build-Time Configuration: If certain extensions need to be installed during the image build stage (such as compiling native extensions),
ARGshould be used. This allows decisions about which components to include at build time, generating customized images for different purposes. - Runtime Configuration: If extensions can be dynamically enabled/disabled when the container starts,
ENVis more appropriate. This allows running containers with different configurations based on the same image, improving image reusability.
For PHP extension scenarios, runtime configuration is generally more suitable. Since PHP extensions can typically be quickly installed via package managers without complex compilation processes, using ENV to control runtime installation offers advantages:
- Maintains generality of the base image
- Allows dynamic configuration adjustment based on deployment environment
- Avoids building separate images for each configuration combination
Hybrid Usage Pattern of ARG and ENV
In certain complex scenarios, combining ARG and ENV can achieve more flexible configuration strategies. This pattern allows setting default values at build time while providing override capability at runtime:
FROM php:7.4-fpm
# Define build arguments with default values
ARG ENABLE_XDEBUG=false
ARG ENABLE_REDIS=false
# Convert build arguments to environment variables
ENV ENABLE_XDEBUG=${ENABLE_XDEBUG}
ENV ENABLE_REDIS=${ENABLE_REDIS}
# Execute conditional installation based on ARG values during build
RUN if [ "${ENABLE_XDEBUG}" = "true" ]; then \
pecl install xdebug && docker-php-ext-enable xdebug; \
fi
# Execute runtime configuration based on ENV values in startup script
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
This pattern offers several advantages:
- Pre-configured image variants can be created at build time using
--build-arg - Configuration can be adjusted at runtime via
-eparameters without rebuilding - Maintains hierarchical and flexible configuration structure
Best Practice Recommendations for Configuration Management
Based on the above analysis, for configuration scenarios similar to PHP extension management, the following strategies are recommended:
- Differentiate Configuration Types: Separate configurations into build-time essentials and runtime options. Core dependencies are fixed at build time, while optional features are decided at runtime.
- Utilize Environment Variable Configuration Files: For extensive runtime configurations, consider using external configuration files. Read and apply configurations in startup scripts:
#!/bin/bash
# entrypoint.sh
# Load custom configuration file if exists
if [ -f "/config/php-extensions.conf" ]; then
source /config/php-extensions.conf
fi
# Install extensions based on configuration
install_extensions() {
local extensions="$@"
for ext in $extensions; do
case $ext in
xdebug) pecl install xdebug && docker-php-ext-enable xdebug ;;
redis) pecl install redis && docker-php-ext-enable redis ;;
# Logic for other extensions
esac
done
}
# Execute extension installation
if [ -n "$PHP_EXTENSIONS" ]; then
install_extensions $PHP_EXTENSIONS
fi
exec "$@"
<ol start="3">
Performance and Security Considerations
When selecting configuration strategies, performance and security factors must also be considered:
- Build-Time Configuration: Results in leaner images with faster startup times but lower flexibility. Suitable for production environment deployment.
- Runtime Configuration: Increases container startup time but provides greater flexibility. Suitable for development and testing environments.
- Security Considerations: Sensitive configurations (such as API keys, database passwords) should be injected at runtime via
ENVto avoid hardcoding in images.
Conclusion
In Docker container configuration management, ARG and ENV each have their appropriate application scenarios. ARG is suitable for parameterization during the build stage, allowing creation of customized image variants; ENV is suitable for dynamic configuration at runtime, improving image reusability and deployment flexibility. For scenarios requiring numerous optional features like PHP extension management, a runtime configuration strategy primarily using ENV is recommended, combined with ARG when necessary to provide build-time default values. Through reasonable configuration layering and externalization, containerized solutions that are both flexible and maintainable can be constructed.
In practical applications, developers should weigh various factors based on specific requirements: frequency of configuration changes, differences in deployment environments, security requirements, and performance considerations. Regardless of the chosen strategy, maintaining configuration clarity, consistency, and documentation capability remains key to successful containerized deployment implementation.