Dockerfile CMD reference
Last reviewed on 2026-09-25
How CMD sets a container's default command, how docker run, Compose and Kubernetes override it, and how it supplies default arguments to ENTRYPOINT.
Syntax
# Exec form (preferred): JSON array, no shell
CMD ["executable", "arg1", "arg2"]
# Default arguments for an exec-form ENTRYPOINT
CMD ["arg1", "arg2"]
# Shell form: run via /bin/sh -c
CMD command arg1 arg2
CMD is a default, not a fixed command: anything passed after the image name in docker run replaces it. It is stored in the image configuration and runs when a container starts — docker build never executes it. Only the last CMD in a Dockerfile takes effect.
Exec form vs shell form
The two forms follow the same rules as for ENTRYPOINT:
- Exec form
CMD ["node", "server.js"]is a JSON array. Use double quotes; with single quotes the line is not valid JSON and Docker falls back to the shell form. No shell runs, so$VARis not expanded, and the program is PID 1 and receivesSIGTERMfromdocker stop. - Shell form
CMD node server.jsruns as/bin/sh -c "node server.js". Variables are expanded, but the shell is PID 1 and may not forward signals, so the container can take the full stop timeout to shut down.
To expand variables in exec form, invoke the shell explicitly and exec the program:
CMD ["sh", "-c", "exec gunicorn --bind 0.0.0.0:\"$PORT\" app:app"]
Both forms can be overridden at run time in exactly the same way.
Overriding CMD at run time
Arguments after the image name replace the entire CMD. They are not appended to it or merged with it:
FROM python:3.12-slim
WORKDIR /app
COPY . .
CMD ["python", "app.py"]
docker run --rm myapp
# runs: python app.py
docker run --rm myapp python manage.py migrate
# runs: python manage.py migrate
docker run --rm -it myapp bash
# runs: bash (interactive shell instead of the app)
Other places that override CMD:
| Tool | Overrides CMD | Overrides ENTRYPOINT |
|---|---|---|
docker run | Arguments after the image name | --entrypoint (also discards CMD) |
| Docker Compose | command: | entrypoint: (also discards the image's CMD) |
| Kubernetes | args: | command: (image CMD is ignored unless you set args:) |
CMD is also inherited: if your Dockerfile has none, the base image's CMD is used. That is why FROM python:3.12-slim with no CMD starts a Python REPL.
CMD with ENTRYPOINT
When an image also has an ENTRYPOINT, CMD stops being the command and becomes the default arguments to it. Run-time arguments then replace only those defaults, not the executable:
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
docker run myimage runs nginx -g "daemon off;"; docker run myimage -t runs nginx -t.
The resulting command for each combination of forms:
No ENTRYPOINT |
ENTRYPOINT exec_entry p1_entry (shell) |
ENTRYPOINT ["exec_entry", "p1_entry"] (exec) |
|
|---|---|---|---|
No CMD |
Error: no command specified | /bin/sh -c exec_entry p1_entry |
exec_entry p1_entry |
CMD ["exec_cmd", "p1_cmd"] |
exec_cmd p1_cmd |
/bin/sh -c exec_entry p1_entry |
exec_entry p1_entry exec_cmd p1_cmd |
CMD exec_cmd p1_cmd |
/bin/sh -c exec_cmd p1_cmd |
/bin/sh -c exec_entry p1_entry |
exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
- A shell-form
ENTRYPOINTignoresCMDcompletely. - A shell-form
CMDunder an exec-formENTRYPOINTpasses/bin/sh -c …as literal arguments. Use the exec form for both. - Setting
ENTRYPOINTin your Dockerfile resets theCMDinherited from the base image. WriteCMDafter it if you want defaults.
Signal handling, --entrypoint, and entrypoint scripts that end in exec "$@" are covered in the ENTRYPOINT reference.
CMD vs RUN vs HEALTHCHECK CMD
- RUN executes during
docker buildand commits the result as an image layer (installing packages, compiling code). CMDexecutes nothing at build time. It only sets metadata for the container's default process.HEALTHCHECK CMDusesCMDas a keyword to introduce a probe command, for exampleHEALTHCHECK CMD curl -f http://localhost/ || exit 1. The probe runs periodically inside the running container alongside the main process; it does not replace the image'sCMD.
Examples
Web application
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER node
CMD ["node", "server.js"]
Calls node directly rather than npm start, so Node is PID 1 and receives SIGTERM.
Default arguments for ENTRYPOINT
FROM alpine:3.20
ENTRYPOINT ["ping", "-c", "3"]
CMD ["localhost"]
docker run pinger pings localhost; docker run pinger 1.1.1.1 replaces only the target.
Shell as the default
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends curl jq \
&& rm -rf /var/lib/apt/lists/*
CMD ["bash"]
A toolbox image: docker run -it toolbox opens bash, docker run toolbox jq --version runs a single tool.
Notes
- Only the last
CMDtakes effect. To start several processes, make the single command a script or a process manager. CMDdoes not add a filesystem layer; it only changes image metadata.- Build-time
ENVandARGsubstitution does not apply toCMD; variables are only expanded at run time, and only by a shell. - Inspect the effective value with
docker image inspect --format '{{json .Config.Cmd}}' myimage.
FAQ
Does docker build run the CMD instruction?
No. CMD only records the default command in the image configuration; it runs when a container starts. Commands that must run during docker build belong in RUN instructions.
How do I override CMD when running a container?
Add a command after the image name: docker run myimage python manage.py migrate. Whatever you pass replaces the whole CMD; it is not merged with it. In Compose use command:, in Kubernetes use args: (or command: if the image has no ENTRYPOINT you want to keep).
Can a Dockerfile have more than one CMD?
You can write several, but only the last CMD takes effect. To run more than one process at start-up, use a script or a process manager as the single command.
Is CMD in HEALTHCHECK the same as the CMD instruction?
No. In HEALTHCHECK CMD curl -f http://localhost/ || exit 1, CMD is a keyword that introduces the health probe command. It runs periodically inside the running container and does not change or replace the container's main CMD.
Should I use CMD or ENTRYPOINT?
Use CMD alone when users should be able to replace the whole command easily, for example docker run myimage bash. Use ENTRYPOINT for the fixed executable and CMD for its default arguments when the image wraps one program.