An image's configured start-up command crashes immediately, so the container never stays up long enough to inspect. How do you get a shell inside that image using `docker run`, and what exactly does the `--entrypoint` flag change?
answer
- --entrypoint replaces Entrypoint only
- args after image still replace CMD
- one token in the flag, arguments after the image
- --entrypoint="" clears it; compose entrypoint: []
- distroless: :debug tag or docker cp/export
basics
~10 sRun docker run --rm -it --entrypoint sh myimage. The flag replaces the image's ENTRYPOINT for that container only; anything you type after the image name still becomes the arguments, replacing CMD.
solid answer
~50 s`docker run --rm -it --entrypoint sh myimage` starts the image with the entrypoint swapped for a shell instead of the failing program, so the filesystem, environment and config are all inspectable. The key mechanic: `--entrypoint` replaces **only** the Entrypoint field. Arguments after the image name still replace CMD, so they become arguments to whatever you supplied: ``` docker run --entrypoint sh myimage -c 'ls -l /app' ``` Use `--entrypoint=""` to clear it entirely and let the first argument be the command. Compose does the same with `entrypoint: []`. Two caveats. First, `--entrypoint` takes a single executable, not a whole command line — extra words go after the image name. Second, minimal and distroless images may have no shell at all; then use the `:debug` variant that ships busybox, or extract the filesystem with `docker create` plus `docker cp`/`docker export`. `docker logs` on the crashed container is still the first thing to check.
code
bash · 5 linesdocker ps -a # exit code
docker logs <container-id>
docker inspect --format '{{json .Config.Entrypoint}}' myimage
docker run --rm -it --entrypoint sh myimage
docker run --rm --entrypoint sh myimage -c 'ls -l /entrypoint.sh; head -1 /entrypoint.sh | xxd | head -1'go deeper
Know the one-liner docker run --rm -it --entrypoint sh myimage and that it only affects that container.
Explain the split between the flag (replaces ENTRYPOINT) and trailing arguments (replace CMD), and the empty-value form that clears the entrypoint.
Lead with logs and exit codes before opening a shell, recognise the classic causes (non-executable script, CRLF shebang, missing runtime libraries), and know the no-shell fallbacks for distroless images.
Weigh debuggability when setting image conventions: mandatory entrypoints and shell-less bases raise incident friction, so pair them with debug tags, ephemeral-debug tooling and documented runbooks.
## Why the normal trick fails With an image whose default command is only CMD, `docker run myimage sh` gives you a shell, because run arguments replace CMD. As soon as the image declares an ENTRYPOINT, that stops working: `sh` is appended as an *argument* to the entrypoint, producing something like `/app/server sh`, which either errors or starts the server anyway. To change the fixed part you need the dedicated flag. ## What `--entrypoint` does `docker run --entrypoint <executable> image [args...]` overrides the image's Entrypoint field for that container only. The image is untouched. The resulting argument vector is `<executable>` followed by whatever you put after the image name, which — as always — replaces CMD. That split is the part people get wrong. The flag accepts **one** token: ``` # wrong: quoted command line is treated as a single binary name docker run --entrypoint "sh -c 'ls /'" img # right: binary in the flag, arguments after the image docker run --rm -it --entrypoint sh img -c 'ls /' ``` To remove the entrypoint entirely rather than replace it, pass an empty value: `docker run --entrypoint="" img ls -l /app`. Now the first argument after the image is the command itself. Docker Compose expresses the same overrides declaratively with `entrypoint:` and `command:`; `entrypoint: []` clears it. ## The debugging sequence A container that exits immediately is not gone — it is stopped, and its logs and metadata remain until removed: 1. `docker ps -a` to find it and read the exit code. 127 means command not found, 126 means found but not executable, 1 usually means the app itself failed. 2. `docker logs <id>` — the crash reason is there most of the time, and this costs nothing. 3. `docker inspect --format '{{json .Config.Entrypoint}} {{json .Config.Cmd}}' image` to see exactly what the image is trying to run, rather than guessing from the Dockerfile. 4. Only then, `docker run --rm -it --entrypoint sh image` to poke around. Common findings once you are inside: the entrypoint script is not executable (fix with `COPY --chmod=755` or a `RUN chmod +x`), it was committed with CRLF line endings so the kernel cannot parse the `#!/bin/sh\r` shebang (the confusing error is `no such file or directory` even though the file plainly exists), or it references an interpreter or shared library the final image does not contain — a frequent outcome of copying a binary out of a multi-stage build into a smaller base. ## When there is no shell Distroless and `FROM scratch` images intentionally ship no `sh`, so `--entrypoint sh` fails with `exec: "sh": executable file not found`. Options: - Use the image's debug variant if one exists — distroless publishes `:debug` tags containing busybox, where `--entrypoint sh` (or `/busybox/sh`) works. - Do not enter the container at all: `docker create` it, then `docker cp` files out or `docker export` the whole filesystem to a tar and inspect it on the host. - Mount the application into a fatter image: `docker run --rm -it -v myvolume:/data alpine sh` for volume contents, or rebuild `--target` an earlier multi-stage stage that still has tooling. ## Related overrides worth knowing - `--user 0` (or `-u root`) when the image drops privileges and the thing you need to inspect is unreadable to the runtime user. - `-e` to change the environment the entrypoint reacts to, since many crashes are a missing or malformed variable. - `docker run --rm --entrypoint env img` to dump the effective environment without a shell. - If the container starts but dies later, `docker exec -it <id> sh` is simpler — `--entrypoint` is specifically for the case where the process dies before you can attach. ## The design lesson The existence of this flag is the cost of an ENTRYPOINT. It is a small cost, and worth paying for single-purpose images, but it is why general-purpose base images leave the entrypoint empty: everyone knows how to `docker run ubuntu bash`, and far fewer reach for `--entrypoint` under pressure.
- The container exits with code 127 and the logs are empty. What does that suggest?Exit code 127 is 'command not found'. Usually the entrypoint path is wrong, the script has CRLF line endings that corrupt the shebang, or the binary is dynamically linked against libraries missing from the final image — common when copying an artifact into a slim or distroless base. Inspecting the file with an overridden entrypoint confirms which.
- How do you inspect a distroless image that has no shell?Use the image's `:debug` tag if it publishes one, since those include busybox and accept `--entrypoint sh`. Otherwise avoid entering it: `docker create` the container and `docker cp` the paths you need out, or `docker export` the whole filesystem to a tar and examine it on the host.
saying these in an interview costs you the question
- Thinking `docker run img sh` opens a shell in an image that declares an ENTRYPOINT.
- Passing a full quoted command line to `--entrypoint` instead of a single executable.
- Assuming the flag permanently modifies the image rather than one container.
- Believing a crashed container is unrecoverable — its logs and metadata persist until it is removed.
- Reaching for `docker exec` on a container that already exited.