Use an exec-form ENTRYPOINT for the executable that defines your container’s job, then use an exec-form CMD for default arguments that callers may replace. A practical pattern is ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] with CMD ["--help"], or an application directly such as ENTRYPOINT ["python", "-m", "myapp"].
Antihost offers VPS plans with one-click Docker, NVMe storage and a 14-day free trial.
The distinction matters at runtime: arguments typed after an image name replace CMD defaults, while docker run --entrypoint replaces ENTRYPOINT itself. Exec form also lets the application become PID 1, which improves signal handling and graceful shutdown.
As an Amazon Associate I earn from qualifying purchases.
Recommended Free Tools
What ENTRYPOINT does
Docker describes ENTRYPOINT as the instruction that configures a container to run as an executable. It establishes the image’s primary command—the process that gives the image its purpose. An image built to run a web server, worker, migration tool, or CLI can therefore behave like that executable when started.
There are two syntaxes:
| Form | Example | How Docker starts it | Important consequence |
|---|---|---|---|
| Exec form | ENTRYPOINT ["executable", "param1", "param2"] |
Runs the executable directly. | Arguments are separate JSON elements; no shell is inserted automatically. |
| Shell form | ENTRYPOINT command param1 param2 |
Runs through the image shell, normally /bin/sh -c on Linux. |
Shell-form ENTRYPOINT ignores CMD and positional arguments supplied to docker run. |
Docker recommends JSON-array syntax for ENTRYPOINT. JSON means double quotes are required, and the executable and every argument occupy their own array element.
#1 Best Overall
The executable role belongs in ENTRYPOINT
Put a stable command in ENTRYPOINT when the image is intended to be run as a particular program. For example:
FROM python:3.13-slim
WORKDIR /app
COPY . .
ENTRYPOINT ["python", "-m", "myapp"]
CMD ["--config", "/etc/myapp/config.yml"]
Every normal start now invokes the Python module. The configuration option is a default, not part of the image’s identity, so a caller can select another file without replacing the executable.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →How ENTRYPOINT and CMD work together
The most useful design pairs an exec-form ENTRYPOINT with an exec-form CMD. The first defines the executable; the second supplies default parameters. Docker appends the CMD array to the ENTRYPOINT array unless the caller provides a replacement argument list.
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
With no extra arguments, Docker starts the equivalent of top -b -c. If the image is started with docker run image -H, Docker starts top -b -H; the supplied list replaces CMD rather than being added after it.
| Command | Effective command | What changed |
|---|---|---|
docker run image |
top -b -c |
Uses the configured defaults. |
docker run image -H |
top -b -H |
Replaces the CMD array while retaining ENTRYPOINT. |
docker run --entrypoint /bin/sh -it image |
/bin/sh |
Replaces ENTRYPOINT itself. |
Why an explicit CMD is often necessary
Docker requires a runnable image to have at least one CMD or ENTRYPOINT command. A base image may already define a CMD, but adding an ENTRYPOINT in your Dockerfile can reset that inherited default. Define the desired CMD in the current Dockerfile instead of relying on an inherited value whose meaning may no longer fit your executable.
Only the final ENTRYPOINT instruction has an effect. Earlier declarations are not combined, so a Dockerfile with several such lines silently uses the last one.
Free tools Windows power users keep installed
One-click scans. No signup required.
Understanding command resolution
Think of the image configuration as two separate arrays. ENTRYPOINT is the part that should remain stable; CMD is the initial value for the argument array. At launch, Docker combines them when both use exec form. Supplying words after the image name replaces the entire CMD array, not just one element and not by appending to the existing defaults.
That distinction explains why a command such as docker run image --config /tmp/test.yml still starts the configured application, while docker run --entrypoint /bin/sh image starts a different executable. The first operation changes parameters; the second changes the image’s executable role for one container.
If operators need to replace the whole command frequently, a fixed ENTRYPOINT may be unnecessarily restrictive. In that case, a plain exec-form CMD can provide a default command while allowing the command after the image name to replace it completely. Choose the arrangement that matches the image’s intended contract rather than adding ENTRYPOINT automatically.
Exec form versus shell form
Use exec form for predictable argument passing
Exec form is a JSON array, not a quoted command line. This is correct:
ENTRYPOINT ["python", "-m", "myapp"]
Docker passes three arguments to the process: python, -m, and myapp. There is no intermediate shell to reinterpret spaces, metacharacters, or variable references.
Exec form does not perform shell expansion. Expressions such as $PORT, pipes, redirection, command chaining, globbing, and shell conditionals are not interpreted automatically. If those features are genuinely part of the design, invoke a shell explicitly and make argument boundaries deliberate:
ENTRYPOINT ["/bin/sh", "-c", "exec myapp "$@"", "--"]
Here the final -- supplies the shell’s $0 value, while arguments passed by Docker become $@. The script uses exec so the shell is replaced by myapp after expansion.
When shell form is appropriate
Shell form can be useful for a command that intentionally depends on shell syntax, but it changes Docker’s override behavior. A shell-form ENTRYPOINT is run as a shell command, and Docker does not append CMD values or positional arguments from docker run in the way exec form does. If users must change flags at launch time, shell form is usually the wrong choice; use exec form or an explicit wrapper that forwards arguments.
PID 1, signals, and graceful shutdown
Docker sends the container’s stop signal to its main process. With an exec-form ENTRYPOINT, the intended application normally becomes PID 1 and can receive SIGTERM directly, perform cleanup, and exit within the runtime’s grace period.
A shell wrapper can sit between Docker and the application. In that arrangement the wrapper is PID 1, and the application may not receive the signal normally. Symptoms include a container that takes the full stop timeout, leaves child processes behind, or exits only after a forced kill.
The standard solution is to end a necessary wrapper with an exec hand-off:
#!/bin/sh
set -eu
# optional setup here
exec "$@"
exec replaces the wrapper process with the final command instead of creating a child that remains behind it. Copy the script into the image and make it executable:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
FROM alpine:3.20
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["--help"]
The Docker build check named JSONArgsRecommended recommends JSON-array CMD and ENTRYPOINT for this signal and process-management reason.
Designing a transparent wrapper
A wrapper is appropriate when startup needs preparation before the long-running program: for example, the script may perform the optional setup documented for the image, then hand control to the command supplied by CMD or by the caller. Keep that script small and explicit. Give it a valid interpreter line, copy it to the path used in ENTRYPOINT, and set execute permission during the build.
Use set -eu when setup errors should stop startup instead of allowing a partially prepared container to continue. Quote argument forwarding exactly as "$@"; this preserves each argument as a separate value, including spaces. A final line such as myapp "$@" starts the application as a child and leaves the script as PID 1. The final line exec myapp "$@", or exec "$@" when the command comes from CMD, replaces the script and restores direct signal delivery.
If a wrapper fails immediately, use an override shell to inspect its path, interpreter, permissions, line endings, and working directory. These checks distinguish a missing file from a valid script that cannot be executed by the chosen base image.
Overriding an image at runtime
Replace default arguments
Put ordinary arguments after the image name when you want to keep the configured executable but change its defaults:
docker run --rm myimage --config /tmp/test.yml
For an exec-form pair, Docker retains ENTRYPOINT and uses --config /tmp/test.yml as the new argument list. This is the normal mechanism for selecting a test configuration, a different subcommand, or a one-off flag.
Replace the executable
Use --entrypoint when debugging startup failures, inspecting an image, or running a maintenance command:
docker run --rm --entrypoint /bin/sh -it myimage
The option changes the executable for that invocation. It does not edit the Dockerfile or alter future containers. Add a command after the image name if the replacement executable needs one, for example docker run --rm --entrypoint /bin/sh -it myimage -c 'ls -la /app'.
A complete implementation workflow
1. Decide what must never change
Identify the program that defines the image’s job. If the image is a Python module, place the interpreter, module switch, and module name in ENTRYPOINT. If startup requires migrations, environment preparation, or file generation, use a wrapper script as the entrypoint.
2. Separate defaults from identity
Flags that operators may change belong in CMD. Keep each token separate in the JSON array. Do not put an entire command line into one element.
3. Add and test any wrapper
A wrapper must exist at the path named in ENTRYPOINT, have a valid interpreter line, and be executable in the image. Use set -eu when appropriate so setup failures do not silently continue, and finish with exec "$@" unless the wrapper intentionally remains the long-running supervisor.
4. Build and inspect the image
Build with your normal tag, then inspect the configured metadata if startup behavior is surprising:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →docker build -t myimage .
docker image inspect myimage
Inspect the image’s Config.Entrypoint and Config.Cmd values. This reveals whether a base-image default was replaced and whether the arrays contain the elements you intended.
5. Exercise all launch paths
- Start without arguments to verify the documented defaults.
- Start with a replacement argument list to verify
CMDoverride behavior. - Start with
--entrypointto verify that emergency access is possible. - Stop the normal container and confirm the application receives termination and exits cleanly.
Testing the image as an interface
Test the image in the same combinations users will rely on. First run it with no arguments and record the effective command. Next provide a complete replacement argument list, not just one token, and verify that the executable remains unchanged. Then launch with --entrypoint /bin/sh (or the shell available in the base image) to confirm that a broken startup can still be inspected. Finally, stop the normal container and watch for clean termination rather than assuming that a successful start proves signal handling is correct.
When a result differs from expectation, compare the Dockerfile with docker image inspect output. Check whether the final ENTRYPOINT is the one you intended, whether Config.Cmd contains an inherited value, and whether every array element is split correctly. This metadata check is faster and more reliable than inferring configuration from a log line alone.
Common mistakes and precise fixes
Putting a whole command in one JSON element
ENTRYPOINT ["python -m myapp"] asks Docker to find an executable literally named python -m myapp. Split it into ENTRYPOINT ["python", "-m", "myapp"].
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsUsing single quotes in exec form
Exec form follows JSON syntax, which requires double quotes. Replace single-quoted elements with valid JSON strings and check commas and brackets.
Expecting environment expansion in exec form
ENTRYPOINT ["myapp", "$PORT"] passes the characters $PORT as an argument; it does not expand the variable. Have the application read its environment, use a wrapper, or invoke an explicit shell when expansion is truly required.
Choosing shell form while expecting overrides
If docker run image new-value appears to have no effect, check whether ENTRYPOINT uses shell form. Convert it to exec form and put replaceable defaults in CMD, or write a wrapper that explicitly forwards arguments.
Forgetting exec in a wrapper
A setup script that ends with myapp "$@" leaves the script as PID 1. Change the final line to exec myapp "$@" or, when the command is supplied by CMD, exec "$@".
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Relying on an inherited CMD
If adding ENTRYPOINT causes an image to start without its former default arguments, define a new CMD in the child Dockerfile. Treat the base image’s command as an implementation detail, not a contract you have not checked.
Defining multiple entrypoints
Docker uses only the last ENTRYPOINT. Remove obsolete lines so the Dockerfile communicates one unambiguous startup design.
Best Value
Choosing the right pattern
| Requirement | Recommended design | Reason |
|---|---|---|
| One fixed application, replaceable flags | Exec-form ENTRYPOINT plus exec-form CMD |
Preserves the executable while allowing argument replacement. |
| Startup preparation before the application | Executable wrapper in ENTRYPOINT, ending with exec "$@" |
Performs setup without sacrificing PID 1 behavior. |
| Shell pipelines or conditionals are intrinsic | Explicit /bin/sh -c with carefully quoted arguments |
Makes shell interpretation intentional and visible. |
| Image mainly used for interactive maintenance | Normal entrypoint plus --entrypoint for one-off shells |
Keeps production startup predictable while retaining a debugging path. |
| Users must freely replace the whole command | Consider relying on CMD rather than a fixed ENTRYPOINT |
A fixed entrypoint constrains the command that follows the image. |
Diagnosing startup and shutdown problems
The container exits immediately
- Check that the executable path exists in the image and has execute permission.
- Inspect
Config.EntrypointandConfig.Cmdfor a missing or unexpectedly inherited value. - Run a shell with
--entrypointand verify the file, interpreter, line endings, and working directory.
Arguments are ignored
- Confirm that
ENTRYPOINTis exec form rather than shell form. - Check whether the wrapper actually forwards
"$@". - Remember that positional arguments replace
CMD; they do not append to it.
docker stop is slow or the app does not clean up
- Check whether a shell or wrapper remains PID 1.
- Use exec-form instructions or finish the wrapper with
exec. - Verify that the application itself handles the termination signal and exits promptly.
Practical checklist
- Is the image’s stable executable in an exec-form
ENTRYPOINT? - Are replaceable defaults in an exec-form
CMD? - Does every executable and argument occupy its own JSON element?
- Are all JSON strings double-quoted?
- If shell syntax is required, is the shell invoked explicitly and are arguments quoted?
- If a wrapper is used, is it copied, executable, and finished with an
exechand-off? - Have you tested normal startup, positional argument overrides,
--entrypointdebugging, and shutdown? - Have you checked the final image metadata rather than assuming the base image’s
CMDsurvived?
Frequently Asked Questions
What does ENTRYPOINT do in a Dockerfile?
It configures the executable a container runs and defines the image’s primary job. Use exec form when that executable should receive arguments and termination signals directly.
What is the difference between ENTRYPOINT and CMD?
ENTRYPOINT identifies the stable executable. CMD supplies default arguments (or, when no ENTRYPOINT is used, a default command) that can be replaced at runtime.
Should I use exec form or shell form?
Prefer exec form for predictable argument boundaries, runtime overrides, and direct signal delivery. Use shell form only when shell expansion, pipelines, redirection, or conditionals are intentionally required.
Why does docker stop not stop my application cleanly?
A shell or wrapper may be PID 1 and may receive the stop signal instead of the application. Use exec-form instructions or end the wrapper with exec "$@", then ensure the application handles termination.
How do I override an ENTRYPOINT?
Pass --entrypoint to docker run, such as docker run --rm --entrypoint /bin/sh -it myimage. This changes only that container invocation.
How do I override CMD without replacing ENTRYPOINT?
Put the replacement arguments after the image name: docker run --rm myimage --config /tmp/test.yml. Those arguments replace the configured CMD array.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Why does ENTRYPOINT [“python -m myapp”] fail?
Each JSON element is one argument, so Docker looks for an executable whose name contains spaces. Use ENTRYPOINT ["python", "-m", "myapp"] instead.
Why did adding ENTRYPOINT remove my base image’s default arguments?
Defining an ENTRYPOINT can reset an inherited CMD. Add the intended CMD explicitly in the current Dockerfile and verify Config.Cmd with docker image inspect.
The Bottom Line
Use exec-form ENTRYPOINT for the executable that gives the image its purpose and pair it with exec-form CMD for replaceable defaults. Choose shell form only for intentional shell behavior, make wrappers end with exec, and use positional arguments or --entrypoint according to whether you are changing defaults or the executable itself.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




