16.2.1 Immediate Exit Problems
A focused guide to Immediate Exit Problems, connecting core concepts with practical Docker and container operations.
Immediate exit problems describe a container that starts and then exits within moments, before doing any meaningful work, a distinct and generally faster category of issue to diagnose than a container that runs for a while before failing, since the cause is almost always something fundamental about the command, image, or configuration rather than an application-level bug that only manifests under specific runtime conditions.
The first and most useful check: exit code
A container's exit code is the single most informative piece of evidence available immediately after an instant exit, and several specific codes have well-known, recognizable meanings:
docker inspect my-api --format '{{.State.ExitCode}}'
0 - the main process exited cleanly, possibly intentionally, possibly because it had nothing to do
1 - a generic application error
126 - command found but not executable (permissions issue)
127 - command not found
137 - killed (commonly SIGKILL, often from an OOM condition or a stop timeout)
139 - segmentation fault
Checking this single value before investigating anything else frequently narrows the cause to one of a small number of well-understood categories immediately.
Exit code 0 with no actual work done
A clean exit code can still represent a real problem if the main process was never actually supposed to exit at all, an entrypoint command meant to start a long-running server that instead runs briefly and exits successfully because of a logic or configuration error:
CMD ["node", "scripts/seed-database.js"]
If this command was mistakenly used as the main CMD instead of the intended server start command, the container runs the seed script, which completes successfully and exits cleanly, exit code 0, leaving no server actually running despite the container appearing to have started without error. Reviewing the actual command being run, not just whether it exited cleanly, is necessary to catch this category of immediate exit.
Exit code 127: command not found
This specific exit code almost always indicates the command specified in CMD or ENTRYPOINT does not exist at the path or name given, which is commonly caused by a typo, a missing executable bit, or a binary that exists in the image at build time but not at the path the runtime command actually references:
CMD ["nodejs", "server.js"]
exec: "nodejs": executable file not found in $PATH
If the image only has node installed, not nodejs, this exact mismatch produces this error; verifying the actual command name and path available inside the image directly resolves ambiguity quickly:
docker run --rm my-api:1.4.0 which node
Exit code 126: permission denied
A command that exists but lacks the executable permission bit produces this specific exit code, commonly encountered with custom scripts copied into an image without their permissions preserved or explicitly set:
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
exec: "/entrypoint.sh": permission denied
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
Explicitly setting the executable bit during the build, rather than assuming a copied file retains whatever permissions it had on the host filesystem, resolves this directly and reliably regardless of how the file's original permissions happened to be set outside the container.
Shell-form versus exec-form CMD differences
The shell form of CMD (without brackets) wraps the command in /bin/sh -c, which can mask or alter how the command itself behaves, particularly around how it receives signals, while the exec form runs the command directly as the container's main process:
CMD node server.js
CMD ["node", "server.js"]
An immediate exit with the shell form that does not reproduce when manually running the equivalent exec-form command can indicate an issue specific to how the shell wrapper interprets the command, particularly if the command itself contains characters or syntax that the shell processes unexpectedly.
Environment variable or configuration causing immediate failure
A container that immediately exits with an application-level error code, rather than one of the more infrastructure-specific codes above, often indicates the application itself failed fast due to missing or invalid required configuration, which is generally the intended, correct behavior for an application designed to fail loudly rather than start in a broken state:
docker logs my-api
Error: Missing required environment variable: DATABASE_URL
Checking the logs, even for a container that exited almost instantly, frequently captures exactly this kind of explicit, self-reported reason, which is usually the fastest path to a resolution for this specific category of immediate exit.
Reproducing the exit interactively
For an immediate exit whose cause is not clear from the exit code and logs alone, starting an interactive shell session using the same image, overriding the default command, allows direct investigation of the environment the failing command would have run in:
docker run -it --rm --entrypoint sh my-api:1.4.0
node server.js
Manually running the exact command that the container's CMD or ENTRYPOINT would have executed, from within this interactive session, often surfaces additional error detail or allows iterative experimentation that the non-interactive, immediate-exit scenario does not.
Checking for missing dependencies inside the image
An immediate exit caused by a missing runtime dependency, a required file, library, or configuration that should have been included during the build but was not, is effectively a build missing-files problem manifesting at runtime rather than being caught during the build itself:
docker run --rm my-api:1.4.0 ls -la /app
Confirming the expected application files and dependencies are actually present in the image, rather than assuming the build process correctly included everything needed, rules out or confirms this category of cause directly.
Common mistakes
- Not checking the exit code first, instead jumping directly to log inspection or other more time-consuming diagnostic steps before ruling in or out the well-known, recognizable exit code categories.
- Assuming a clean exit code (0) means nothing is wrong, without verifying the container was actually meant to keep running rather than complete and exit.
- Not setting executable permissions explicitly on a copied script, relying on host filesystem permissions that may not transfer correctly into the image.
- Using shell-form
CMDwithout considering whether the shell wrapper itself might be altering the command's behavior in a way that contributes to the immediate exit. - Not reproducing the failing command interactively when logs and exit code alone do not provide a clear enough answer.
Immediate exit problems are usually fast to diagnose precisely because the cause is almost always fundamental, command, permissions, configuration, rather than a subtle application bug, and checking the exit code first, then logs, then reproducing the command interactively if needed, resolves the large majority of cases without requiring an extensive investigation.