1.06 Docker CMD vs ENTRYPOINT
Overview
CMD and ENTRYPOINT are Dockerfile instructions that define what runs when a container starts. Understanding the difference is essential for building flexible, reusable images.
Abstract
CMD sets a default command that is fully replaced if you pass arguments at runtime. ENTRYPOINT sets a fixed executable that always runs, with any runtime arguments appended to it. Combining both gives you a default with an override β the most flexible pattern.
Why It Matters in Production
Containers are not virtual machines. They exist to run one specific process β and when that process ends, the container exits. Getting CMD and ENTRYPOINT right means your images behave predictably whether run manually, in CI/CD pipelines, or orchestrated by Kubernetes.
Key Concepts
| Instruction | Behavior | Runtime Override |
|---|---|---|
CMD |
Sets the default command and/or parameters | Completely replaced by anything passed after the image name |
ENTRYPOINT |
Sets the fixed executable to run | Appended to by runtime args; replaced only with --entrypoint flag |
CMD + ENTRYPOINT |
CMD provides default args to ENTRYPOINT |
Runtime args replace CMD portion only; ENTRYPOINT stays fixed |
Common Use Cases
CMDβ Images where you want a sensible default but full flexibility to override (e.g. Ubuntu defaulting tobash)ENTRYPOINTβ Images designed as executables, where the program is fixed and only arguments vary (e.g. a customsleeporbackuptool)ENTRYPOINT+CMDβ Best of both: a fixed program with a configurable default argument that can still be overridden at runtime
How Containers Exit
A container only lives as long as its main process. When the process finishes or crashes, the container exits.
# Ubuntu exits immediately β bash finds no terminal and quits
docker run ubuntu
# Override the default command to keep the container alive for 5s
docker run ubuntu sleep 5
Example Configuration or Commands
Nginx and MySQL β CMD in real images
# Nginx Dockerfile (simplified)
CMD ["nginx"]
# MySQL Dockerfile (simplified)
ENTRYPOINT ["/entrypoint.sh"]
CMD ["mysqld"]
Ubuntu base image β CMD defaults to bash
Custom sleeper image using CMD
# Build the image
docker build -t ubuntu-sleeper .
# Run with default (sleeps 5s)
docker run ubuntu-sleeper
# Override CMD entirely β sleeps 10s instead
docker run ubuntu-sleeper sleep 10
CMD β shell form vs JSON array form
# Shell form (works, but avoid for ENTRYPOINT/CMD best practice)
CMD sleep 5
# JSON array form β CORRECT: executable and args are separate elements
CMD ["sleep", "5"]
# JSON array form β WRONG: do not combine executable and args as one string
# CMD ["sleep 5"] β this will fail
JSON Array Rule
Always use the JSON array format for CMD and ENTRYPOINT. The first element must be the executable. Never combine the command and its arguments into a single string element.
Custom sleeper image using ENTRYPOINT
# The argument is appended to ENTRYPOINT β runs: sleep 10
docker run ubuntu-sleeper 10
# Running without an argument causes an error
docker run ubuntu-sleeper
# sleep: missing operand
# Try 'sleep --help' for more information.
Combining ENTRYPOINT with CMD for a default argument
# No argument passed β uses CMD default: sleep 5
docker run ubuntu-sleeper
# Argument passed β overrides CMD: sleep 10
docker run ubuntu-sleeper 10
Overriding ENTRYPOINT at runtime
# Replace the entrypoint with a different executable entirely
docker run --entrypoint sleep2.0 ubuntu-sleeper 10
# Command at startup: sleep2.0 10
CMD vs ENTRYPOINT β Behaviour Summary
| Scenario | Dockerfile | docker run command |
Command at startup |
|---|---|---|---|
| CMD only, no runtime arg | CMD sleep 5 |
docker run ubuntu-sleeper |
sleep 5 |
| CMD only, runtime arg | CMD sleep 5 |
docker run ubuntu-sleeper sleep 10 |
sleep 10 |
| ENTRYPOINT only, with arg | ENTRYPOINT ["sleep"] |
docker run ubuntu-sleeper 10 |
sleep 10 |
| ENTRYPOINT only, no arg | ENTRYPOINT ["sleep"] |
docker run ubuntu-sleeper |
sleep β error |
| ENTRYPOINT + CMD, no arg | ENTRYPOINT ["sleep"] CMD ["5"] |
docker run ubuntu-sleeper |
sleep 5 |
| ENTRYPOINT + CMD, with arg | ENTRYPOINT ["sleep"] CMD ["5"] |
docker run ubuntu-sleeper 10 |
sleep 10 |
| Override entrypoint | ENTRYPOINT ["sleep"] |
docker run --entrypoint sleep2.0 ubuntu-sleeper 10 |
sleep2.0 10 |
Best Practices
Best Practices
- Always write
CMDandENTRYPOINTin JSON array format β shell form has subtle differences in signal handling and variable expansion - Use
ENTRYPOINT+CMDwhen your image is a purpose-built tool:ENTRYPOINTis the command,CMDis the safe default argument - Use
CMDonly when the image is a general base and the user should fully control what runs - Keep the entrypoint executable simple β use a wrapper shell script (
entrypoint.sh) for complex init logic - Document all supported runtime arguments in your image's README
Security Best Practices
Security
- Avoid running containers as root β set a non-root
USERin your Dockerfile above theENTRYPOINT/CMDline - Do not embed secrets or credentials in
CMDorENTRYPOINTβ they are visible indocker inspectand image layers - Prefer specific executable paths (e.g.
/usr/bin/sleep) over relying onPATHresolution inside containers - If using a shell wrapper as your entrypoint, validate and sanitize any arguments it processes
Do and Don't
| β Do | β Don't |
|---|---|
Use JSON array format: CMD ["sleep", "5"] |
Use shell string in arrays: CMD ["sleep 5"] |
Use ENTRYPOINT + CMD for default-with-override pattern |
Use CMD alone when the executable should always be fixed |
Override ENTRYPOINT with --entrypoint when needed |
Assume runtime args replace the entrypoint β they don't |
Use a wrapper entrypoint.sh for complex init logic |
Put multi-step init logic directly in ENTRYPOINT |
Test both docker run image and docker run image arg |
Ship an image without verifying the no-arg case |
Common Mistakes
Common Mistakes
- Writing
CMD ["sleep 5"]β the command and argument must be separate array elements:CMD ["sleep", "5"] - Expecting
ENTRYPOINTto be replaced by runtime args β onlyCMDis replaced; use--entrypointto overrideENTRYPOINT - Forgetting that
CMDis completely discarded when any argument is passed at runtime β even if you only wanted to append - Using shell form (
CMD sleep 5) withENTRYPOINTβ the JSON format is required forCMDto act as default args toENTRYPOINT - Not handling the missing-argument case when using
ENTRYPOINTalone β always pair it with aCMDdefault
Troubleshooting
Container exits immediately
# Check what command the container ran
docker ps -a
docker logs <container_id>
# Inspect the image's configured entrypoint and cmd
docker inspect <image_name> | grep -A5 '"Cmd"'
docker inspect <image_name> | grep -A5 '"Entrypoint"'
sleep: missing operand error
The container used ENTRYPOINT ["sleep"] with no CMD default and no argument was passed at runtime. Fix:
Overriding the entrypoint for debugging
# Drop into a shell instead of running the default entrypoint
docker run --entrypoint /bin/bash -it ubuntu-sleeper
Quick Recap
- Containers run one process; when that process ends, the container exits
CMDβ default command, fully replaced by runtime argumentsENTRYPOINTβ fixed executable, runtime arguments are appended- Use
ENTRYPOINT ["exec"] + CMD ["default-arg"]for the most flexible pattern - Always use JSON array format for both instructions
- Override
ENTRYPOINTat runtime withdocker run --entrypoint <new-cmd>
Interview / Revision Notes
-
Q: What is the difference between
CMDandENTRYPOINT?CMDsets a default command that is fully replaced by runtime args.ENTRYPOINTsets a fixed executable; runtime args are appended to it. -
Q: How do you provide a default argument that can still be overridden? Combine both:
ENTRYPOINT ["sleep"]andCMD ["5"]. Runtime arg overridesCMD;ENTRYPOINTstays fixed. -
Q: How do you override
ENTRYPOINTat runtime?docker run --entrypoint <new-executable> image [args] -
Q: Why must
CMDandENTRYPOINTuse JSON array format? Shell form doesn't supportCMDacting as default args toENTRYPOINT. JSON format also handles signals correctly. -
Q: Why does
docker run ubuntuexit immediately? Ubuntu's defaultCMDisbash. Docker doesn't attach a terminal by default, so bash exits, and with it, the container.