Exit Code 126 (Cannot Execute) in Docker & Kubernetes
Exit code 126 means the runtime found the entrypoint path but could not execute it. Either the file is not executable (EACCES), the mount is noexec, or the kernel rejected the binary format (ENOEXEC, normally a CPU architecture mismatch). The interpreter never started, so this is not an application error.
Proof commands: confirm the exit status and the killer
Run these before changing anything. The first two identify what the runtime recorded; the third finds a kernel-level kill on the host. Replace the placeholder container ID, pod name or host path with your own.
Docker inspect
docker inspect <container_id> --format '{{.State.Status}} | ExitCode: {{.State.ExitCode}} | Error: {{.State.Error}}'Kubernetes state
kubectl get pod <pod_name> -o jsonpath='{range .status.containerStatuses[*]}{.name}{"\t"}{.lastState.terminated.reason}{"\tExit:"}{.lastState.terminated.exitCode}{"\n"}{end}'Mode and format
docker run --rm --entrypoint /bin/sh <image> -c 'ls -l /entrypoint.sh; file /entrypoint.sh; uname -m'A permission problem and an architecture mismatch both surface as could not execute. docker inspect shows the exit status but not the errno, so run the entrypoint once by hand with the same user and mounts. If file reports ELF 64-bit LSB ... x86-64 while uname -m says aarch64, the image is simply the wrong architecture.
Three production root causes
The runtime found the entrypoint path but could not execute it: permission denied, a noexec mount or a bad binary format. Check chmod +x in the Dockerfile and confirm the image architecture matches uname -m. The logs stay empty because the command never ran.
1. The entrypoint is missing its executable bit
COPY from a Windows checkout or an archive may preserve mode 0644. The runtime then reports permission denied and exits 126. The fix belongs in the build: chmod +x in the Dockerfile, with an exec-form ENTRYPOINT that names the script directly. chmod on the host is not enough after the file has been copied.
2. The image architecture does not match the host
Running an amd64 image on an arm64 host without emulation produces exec format error. Verify docker image inspect <image> --format '{{.Os}}/{{.Architecture}}' against uname -m. Build multi-arch images with buildx or select the right platform explicitly instead of relying on emulation in production.
3. A noexec mount or wrong interpreter path
A bind mount or volume with noexec turns an otherwise executable file into EACCES. A shebang pointing at /bin/bash on an image that only has /bin/sh can produce a similar failure, though a missing interpreter often surfaces as 127. Check findmnt -no OPTIONS -T /path and the exact shebang.
Copy-ready fixes for Docker Compose and Kubernetes
The two manifests set explicit memory limits and a termination grace period. Use them as a baseline, then adjust the values to the measured working set of the service.
docker-compose.yml
For local development on ARM hosts, set platform: linux/amd64 only when the image has no arm64 build, and expect emulation to be slow. A permission fix belongs in the Dockerfile; a bind-mounted script that changes mode on the host is fragile.
services:
app:
image: ghcr.io/acme/app:1.4.2
restart: on-failure:3
stop_grace_period: 10s
deploy:
resources:
limits:
memory: 256M
reservations:
memory: 128M
deployment.yaml
The same mode rules apply in Kubernetes, and the container user must be able to execute and read the file. A runAsUser that does not match the image's ownership can cause permission denied even when the exec bit is set. Keep the binary's mode and owner in the image, not in a runtime mount.
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 2
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
terminationGracePeriodSeconds: 20
containers:
- name: app
image: ghcr.io/acme/app:1.4.2
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
Make the entrypoint executable and explicit
The exec form avoids a shell lookup and makes the failing path obvious.
FROM alpine:3.20
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod 0755 /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]Frequently asked questions
How do I fix exit code 126 in Docker?
Check three things in order: the entrypoint's executable bit, the image architecture against the host, and whether the file lives on a noexec mount. Fix the mode in the Dockerfile with chmod +x and use the exec form of ENTRYPOINT. Rebuild and run the image once without Compose to confirm.
What is the difference between exit codes 126 and 127?
126 means the runtime found the path but could not execute it: permission denied, bad format or noexec. 127 means the runtime could not find the command at all: a missing binary, a broken symlink, bash absent from Alpine, or a missing dynamic loader. The path exists for 126 and does not for 127.
Why does exec format error happen on Apple Silicon?
The host is arm64 and the image is amd64. Docker can emulate it only when the emulator is available; otherwise execve fails with ENOEXEC. Build or pull an arm64 image, or select platform: linux/amd64 deliberately and make sure the binfmt emulator is installed.
Related exit codes, signals and network references
Follow the status you actually observed, then check the related port or calculator when the failure involves networking, exposure or firewall rules.
Reference basis: POSIX signal semantics (128 + n), Docker container exit status conventions, and Kubernetes container termination behaviour. Verify the exact behaviour against your runtime version before relying on it in an incident.
Last reviewed 2026-11-06 · All exit codes · Developer tools · Privacy