When writing a Dockerfile
, two common instructions define what should run inside a container by default: CMD
and ENTRYPOINT
. Although they may seem similar at first glance, they serve different purposes and behave differently—especially when overriding commands at runtime.
In this blog post, we’ll explore the differences between CMD
and ENTRYPOINT
, how they work, when to use them, and how they can be used together effectively.
🧠 Purpose of CMD
and ENTRYPOINT
Directive | Purpose |
---|---|
CMD | Provides default arguments for the container’s main process. |
ENTRYPOINT | Defines the main executable that always runs. |
They both define what happens when a container starts, but their behavior around overrides and flexibility is key to understanding the difference.
✅ CMD
: Default Command/Arguments
The CMD
instruction defines the default command to run when the container starts. It can be overridden by providing arguments when using docker run
.
📌 Example:
FROM ubuntu
CMD ["echo", "Hello from CMD"]
Run:
docker build -t cmd-demo .
docker run cmd-demo
Output:
Hello from CMD
You can override CMD
at runtime:
docker run cmd-demo echo "Overridden!"
Output:
Overridden!
🔄 Key Point:
CMD
is ignored if arguments are passed todocker run
.
✅ ENTRYPOINT
: Fixed Executable
The ENTRYPOINT
instruction sets the main command that always runs. Even if arguments are passed during docker run
, ENTRYPOINT
is not replaced—only its arguments change.
📌 Example:
FROM ubuntu
ENTRYPOINT ["echo"]
Run:
docker build -t entrypoint-demo .
docker run entrypoint-demo Hello from ENTRYPOINT
Output:
Hello from ENTRYPOINT
Even though we passed arguments, echo
from the ENTRYPOINT
was still used.
✅ Using CMD
+ ENTRYPOINT
Together
You can combine them for more flexible container behavior.
📌 Example:
FROM ubuntu
ENTRYPOINT ["echo"]
CMD ["Hello from CMD"]
Run:
docker build -t combo-demo .
docker run combo-demo
Output:
Hello from CMD
Now try overriding the default argument:
docker run combo-demo Hello from override
Output:
Hello from override
🔄 Summary:
ENTRYPOINT
: Defines what to run.CMD
: Defines default arguments.
✅ Shell vs Exec Form
Both CMD
and ENTRYPOINT
can be written in two forms:
Exec form (preferred):
ENTRYPOINT ["executable", "param1"]
CMD ["param2"]
Shell form:
ENTRYPOINT executable param1
CMD param2
⚠️ Shell form runs commands via
/bin/sh -c
, which can affect signal handling (e.g., withSIGTERM
). Use exec form for better behavior in production.
🧠 Which One Should I Use?
Use Case | Recommended Directive |
---|---|
Fixed behavior, always run same app | ENTRYPOINT |
Set default behavior, allow override | CMD |
Combine command + default args | Use both together |
Shell scripts or pipelines | ENTRYPOINT (shell form) |
✅ Summary
Feature | CMD | ENTRYPOINT |
---|---|---|
Defines what runs | ✅ (default, can be overridden) | ✅ (main command, not overridden) |
Overridden by docker run | ✅ Completely | ❌ Only args can be overridden |
Can be used together | ✅ Yes | ✅ Yes |
Form options | Exec & Shell | Exec & Shell |
🚀 Final Tip
To create a robust container with optional arguments and a fixed process:
ENTRYPOINT ["python3", "app.py"]
CMD ["--host=0.0.0.0"]
Now users can override flags, but app.py
always runs.