Docker Error: 'OCI runtime exec failed — executable file not found in $PATH'
Fix Docker's 'OCI runtime exec failed: unable to start container process: exec: executable file not found in $PATH' — install the binary, use an absolute path, or fix exec vs shell form.
- #docker
- #troubleshooting
- #errors
- #runtime
Exact Error Message
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "myapp": executable file not found in $PATH: unknown
Common variants — the quoted binary changes, and older/other runtimes word it slightly differently:
... starting container process caused: exec: "bash": executable file not found in $PATH: unknown
OCI runtime exec failed: exec failed: unable to start container process: exec: "psql": executable file not found in $PATH: unknown
What It Means
This is a specific tail of the broader OCI runtime create failed error. The image pulled, the container’s namespaces and filesystem were set up, and then runc tried to launch the first process — the program named by your ENTRYPOINT/CMD (or the command you passed to docker run / docker exec). The runtime searched every directory in the container’s PATH, found no such executable, and refused to start.
The key insight: PATH is evaluated inside the container, using the container’s filesystem — not your host’s. A binary that exists on your laptop, or that you assumed was in the base image, simply isn’t there. Minimal images (scratch, alpine, distroless, busybox) ship almost nothing, so this error is extremely common when moving from a fat base image to a slim one.
There are really two distinct failures hiding under the same message. The first is “the program does not exist in this image at all” — you never installed it, or a multi-stage build left it behind in an earlier stage. The second is “the program exists but the runtime can’t resolve the name you gave it” — it lives in a directory that isn’t on PATH, or you typed bash in an image that only has sh. The diagnostic steps below distinguish these in seconds, and the distinction determines whether you fix the Dockerfile’s install steps or simply fix the path/name you reference.
Common Causes
- Binary not installed in the image. The
ENTRYPOINT/CMDreferences a tool that was neverapt installed /apk added into the final image. bashdoesn’t exist — onlyshdoes. Alpine and busybox ship/bin/sh(BusyBox), not/bin/bash.CMD ["bash", ...]fails;CMD ["sh", ...]works.- Wrong or relative path.
CMD ["myapp"]relies onPATH; if the binary lives in/opt/app/binand that isn’t onPATH, it’s “not found.” - Shell-form vs exec-form confusion.
ENTRYPOINT myapp(shell form) runs via/bin/sh -c, which fails differently ifshis absent; exec form["myapp"]needs the binary directly. PATHnot set in ascratchimage. With no shell profile,PATHmay be empty, so even/usr/bin/myappisn’t found unless invoked by absolute path.- Cross-architecture binary. An
amd64binary copied into anarm64image won’t execute; the runtime reports it as not found/exec error.
How to Reproduce the Error
Reliable. Ask an Alpine image to run bash, which it does not contain:
docker run --rm alpine bash -c 'echo hi'
# ... exec: "bash": executable file not found in $PATH: unknown
Or reference a binary that was never installed:
docker run --rm alpine psql --version
# ... exec: "psql": executable file not found in $PATH: unknown
Diagnostic Commands
The fastest move is to get a shell in the same image and look for the binary yourself.
# Override the entrypoint and open a shell to inspect the filesystem
docker run --entrypoint sh -it <image>
# inside the container:
echo "$PATH"
command -v myapp || which myapp
ls -l /usr/local/bin /usr/bin | grep myapp
# What did the image's metadata configure as entrypoint/cmd?
docker inspect <image> --format 'ENTRYPOINT={{json .Config.Entrypoint}} CMD={{json .Config.Cmd}} PATH={{json .Config.Env}}'
# Confirm the architecture matches the host
docker inspect <image> --format '{{.Architecture}}'
docker version --format '{{.Server.Arch}}'
Example showing the binary genuinely isn’t present:
/ # echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/ # command -v psql
/ # <-- empty: psql is not installed anywhere on PATH
Step-by-Step Resolution
-
Confirm the binary is missing using the shell-override above. If
command -vprints nothing, the binary truly isn’t in the image. -
Install it in the image. Add it to the Dockerfile of the final stage:
# Debian/Ubuntu base RUN apt-get update && apt-get install -y --no-install-recommends postgresql-client \ && rm -rf /var/lib/apt/lists/* # Alpine base RUN apk add --no-cache postgresql-client -
If it’s a shell mismatch, use
sh(or install bash). On Alpine either switch the form or add bash:# Option A: use the shell that exists CMD ["sh", "-c", "echo hi"] # Option B: install bash if you truly need it RUN apk add --no-cache bash -
Use an absolute path for non-standard locations. If your binary lives outside
PATH, reference it fully:ENTRYPOINT ["/opt/app/bin/myapp"] -
Prefer exec form over shell form. Exec form avoids an implicit
/bin/shdependency and is what production should use:# exec form (preferred) ENTRYPOINT ["myapp", "--serve"] # shell form (needs /bin/sh present) ENTRYPOINT myapp --serve -
For multi-stage builds, COPY the binary into the final stage. A classic bug: you build in a
golangstage but the finalscratch/alpinestage never receives the binary.FROM golang:1.22 AS build WORKDIR /src COPY . . RUN CGO_ENABLED=0 go build -o /out/myapp . FROM alpine:3.20 COPY --from=build /out/myapp /usr/local/bin/myapp ENTRYPOINT ["/usr/local/bin/myapp"] -
Fix cross-arch mismatches. Build for the target platform:
docker buildx build --platform linux/arm64 ..., and don’tCOPYa prebuilt host binary of the wrong architecture.
How to Prevent the Issue
- Use exec form (
["binary", "arg"]) and absolute paths forENTRYPOINT/CMDso resolution never depends on shell orPATHquirks. - Remember Alpine/BusyBox/distroless ship
sh, notbash— write scripts for POSIXshor explicitly install bash. - In multi-stage builds, verify the final stage
COPY --from=...actually pulls every runtime binary it needs. - Build static binaries (
CGO_ENABLED=0) forscratch/distroless so there’s no shell or loader dependency at all. - Match
--platformto your deployment architecture in CI to avoid silent cross-arch “not found” failures. - Add a one-line health check to CI that runs the image’s entrypoint with
--versionor--help; if the binary is missing, this fails the build instead of the production deploy. - When slimming a base image (moving from
ubuntutoalpineor distroless), re-test every command the container actually invokes — package managers, shells, and helper tools you took for granted often vanish in the smaller image.
Related Docker Errors
- Docker Error: OCI runtime create failed: runc create failed
- Docker Error: Cannot connect to the Docker daemon
- Docker Error: Got permission denied while trying to connect to the Docker daemon socket
- More in the Docker guides.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.