When building Docker images, two critical instructions you'll often encounter are ENTRYPOINT
and CMD
. While both define commands that a container executes when it starts, they serve distinct purposes. In this post, we’ll break down the differences between ENTRYPOINT
and CMD
and show how to use them effectively with real-world examples.
What Are ENTRYPOINT and CMD?
ENTRYPOINT
ENTRYPOINT
defines the main command that always runs when the container starts. It is ideal when you want your container to execute a specific script or process consistently, regardless of additional user input. While ENTRYPOINT
can accept arguments, the primary command is fixed.
CMD
CMD
serves as a way to provide default arguments to ENTRYPOINT
. If no ENTRYPOINT
is defined, CMD
acts as the primary command itself. The beauty of CMD
is its flexibility—it can be overridden when running the container, making it ideal for specifying default behavior that can easily be customized.
Key Differences
-
ENTRYPOINT
is used to define the main process that a container should always run. -
CMD
supplies default arguments toENTRYPOINT
, or, if noENTRYPOINT
is defined, it acts as the default command.
Example 1: Using a Command in ENTRYPOINT
In this first example, we’ll set a fixed command with ENTRYPOINT
and provide a default argument with CMD
.
Dockerfile:
# Base image
FROM alpine:latest
# Set ENTRYPOINT to a fixed command
ENTRYPOINT ["ping"]
# CMD provides default arguments to ENTRYPOINT
CMD ["google.com"]
Explanation:
-
ENTRYPOINT
is set toping
, meaning that command will always run when the container starts. -
CMD
provides the default argumentgoogle.com
for theping
command.
Building the docker image my-ping-image
:
docker build -t my-ping-image:v1.0.0 . -f Dockerfile.ping
Running the container without arguments:
docker run --name google-ping-container my-ping-image:v1.0.0
This will execute:
ping google.com
Overriding CMD:
docker run --name localhost-ping-container my-ping-image:v1.0.0 localhost
This overrides CMD
, and the container will now execute:
ping localhost
Example 2: Using a Shell Script in ENTRYPOINT with CMD for Environment-Specific Behavior
Now, let’s look at a more complex use case. We’ll use ENTRYPOINT
to run a shell script that generates an index.html
file dynamically based on the environment (development
or production
). The CMD
will specify the environment, with a default of development
.
Scenario:
You want to run an Nginx container that serves different content based on the environment. The index.html
file will be created dynamically by a shell script using ENTRYPOINT
, and the environment can be specified via CMD
.
Dockerfile:
# Base image
FROM nginx:latest
# Install necessary utilities
RUN apt-get update && apt-get install -y bash
# Copy entrypoint script to the container
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
# Set ENTRYPOINT to the shell script
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
# CMD provides default environment (development)
CMD ["development"]
Shell Script (entrypoint.sh
):
#!/bin/bash
# Get the environment from CMD or default to development
ENVIRONMENT=$1
# Create the index.html file based on the environment
if [ "$ENVIRONMENT" == "development" ]; then
echo "<h1>Welcome to the Development Page</h1>" > /usr/share/nginx/html/index.html
else
echo "<h1>Welcome to the Production Page</h1>" > /usr/share/nginx/html/index.html
fi
# Start Nginx in the foreground
nginx -g 'daemon off;'
Explanation:
-
ENTRYPOINT
: The script/usr/local/bin/entrypoint.sh
will always run when the container starts. This script generates theindex.html
file based on the environment (either development or production). -
CMD
: The default argument isdevelopment
, so by default, the container will serve a "development" page.
Building the docker image my-nginx-app
:
docker build -t my-nginx-app:v1.0.0 . -f Dockerfile.shell
Running the container without arguments (default to development):
docker run -d -p 8080:80 --name development-nginx-container my-nginx-app:v1.0.0
This will generate an index.html
file containing:
<h1>Welcome to the Development Page</h1>
Visit http://localhost:8080
to see the development page.
Overriding CMD to run in production:
docker run -d -p 8081:80 --name production-nginx-container my-nginx-app:v1.0.0 production
This will generate an index.html
file containing:
<h1>Welcome to the Production Page</h1>
Now, visiting http://localhost:8081
will show the production page.
Key Takeaways
-
ENTRYPOINT
defines a command that will always run when the container starts. It is well-suited for containers that must always perform a specific action (e.g., starting a web server or database). -
CMD
provides default arguments toENTRYPOINT
. If there’s noENTRYPOINT
,CMD
acts as the primary command itself. It's flexible, allowing you to customize the behavior of your containers easily.
When to Use ENTRYPOINT
Use ENTRYPOINT
when you need the container to run a specific process consistently, like a web server, background service, or database.
When to Use CMD
Use CMD
to provide default arguments or when you want to allow users to override the command without altering the core functionality of the container.
Conclusion
By understanding the differences between ENTRYPOINT
and CMD
, you can build flexible, reusable Docker containers. ENTRYPOINT
ensures that a container always performs a specific action, while CMD
lets you adjust that behavior without changing the container's core functionality. Together, they provide a powerful combination for building efficient Docker images, as demonstrated by the examples above. Whether you're configuring a simple utility or dynamically creating environment-based content, mastering these instructions will enhance your Docker workflows.
Top comments (0)