Initializing Enclave...

How to Fix Docker 'standard_init_linux.go:211: exec user process caused: no such file or directory'

Threat/Impact Level: CRITICAL | Exploitability/Downtime Risk: HIGH | Time to Fix: 5 mins

TL;DR

  • What broke: Docker's Linux init layer cannot execute your entrypoint — the file either has Windows CRLF line endings, a wrong shebang, missing execute bit, or simply doesn't exist at the declared path inside the image.
  • How to fix it: Strip CRLF endings with dos2unix, verify the shebang, chmod +x the script, and confirm the binary path is valid inside the container filesystem.
  • Fast path: Use our Client-Side Sandbox below to auto-refactor your Dockerfile and entrypoint script — paste both and get corrected code instantly.

The Incident (What Does the Error Mean?)

Raw error output from docker run or your Kubernetes pod events:

standard_init_linux.go:211: exec user process caused: no such file or directory

This fires inside runc's init process — the very first thing that runs inside the container namespace. The kernel's execve() syscall returned ENOENT. Your application process never started. The container exits with code 1 immediately. In Kubernetes this manifests as CrashLoopBackOff within seconds of scheduling.

Despite the message saying "no such file or directory", the script file itself usually exists. The error is thrown by the kernel when it cannot find the interpreter declared in the shebang line (e.g., #!/bin/bash when bash isn't installed, or a path with invisible \r characters corrupting the interpreter path).


The Attack Vector / Blast Radius

This is a full deployment blocker. Every replica of your service fails simultaneously on rollout. In a CD pipeline with auto-deploy, a single bad commit carrying a CRLF-encoded entrypoint script takes down all pods in the Deployment. kubectl rollout undo is your immediate escape hatch, but the root cause will re-emerge on every subsequent deploy until fixed at the source.

Cascading failure chain:

  1. New image pushed → rolling update starts
  2. All new pods hit CrashLoopBackOff
  3. If maxUnavailable is misconfigured, old pods are terminated before new ones are healthy
  4. Service goes dark

The CRLF variant is especially insidious because cat entrypoint.sh looks perfectly normal in a Windows terminal. The corruption is invisible without cat -A or hexdump.


How to Fix It (The Solution)

Diagnose First

Run these inside your build context before building:

# Detect CRLF — if you see ^M at line endings, that's your culprit
cat -A entrypoint.sh | head -5

# Verify shebang interpreter exists in the base image
docker run --rm <base-image> which bash
docker run --rm <base-image> ls -la /bin/sh

# Inspect the built image filesystem directly
docker run --rm --entrypoint sh <your-image> -c "ls -la /app/entrypoint.sh"

Root Cause 1 — CRLF Line Endings (Most Common)

- #!/bin/bash\r\n          ← Windows line ending, kernel sees interpreter as "/bin/bash\r"
- set -e\r\n
- exec "$@"\r\n

+ #!/bin/bash
+ set -e
+ exec "$@"

Fix in Dockerfile:

  COPY entrypoint.sh /entrypoint.sh
+ RUN sed -i 's/\r$//' /entrypoint.sh && chmod +x /entrypoint.sh
  ENTRYPOINT ["/entrypoint.sh"]

Or fix at the source permanently with dos2unix entrypoint.sh and commit the clean file.


Root Cause 2 — Missing Execute Permission

  COPY entrypoint.sh /entrypoint.sh
- ENTRYPOINT ["/entrypoint.sh"]

+ RUN chmod +x /entrypoint.sh
+ ENTRYPOINT ["/entrypoint.sh"]

Root Cause 3 — Wrong Shebang / Missing Interpreter

- #!/bin/bash        ← bash not present in alpine-based images

+ #!/bin/sh          ← sh is always available

Or install bash explicitly:

  FROM alpine:3.19
+ RUN apk add --no-cache bash
  COPY entrypoint.sh /entrypoint.sh
  RUN chmod +x /entrypoint.sh
  ENTRYPOINT ["/entrypoint.sh"]

Root Cause 4 — Shell Form vs Exec Form Entrypoint

If your ENTRYPOINT uses shell form, Docker wraps it in /bin/sh -c, which can mask path issues. Always use exec form for entrypoints:

- ENTRYPOINT /entrypoint.sh

+ ENTRYPOINT ["/entrypoint.sh"]

Enterprise Best Practice

For production images, enforce entrypoint hygiene in a multi-stage build and validate during CI:

  FROM node:20-alpine AS builder
  WORKDIR /app
  COPY . .
  RUN npm ci && npm run build

  FROM node:20-alpine AS runtime
  WORKDIR /app
  COPY --from=builder /app/dist ./dist
  COPY entrypoint.sh /entrypoint.sh
+ RUN dos2unix /entrypoint.sh 2>/dev/null || sed -i 's/\r$//' /entrypoint.sh \
+     && chmod 550 /entrypoint.sh \
+     && sh -n /entrypoint.sh
  USER node
  ENTRYPOINT ["/entrypoint.sh"]

The sh -n /entrypoint.sh performs a syntax-only check at build time — if the script is unparseable, the image build fails, not the runtime.


💡 Tired of pasting proprietary configs into ChatGPT? Generic AI tools log your company's ARNs, DB strings, and private keys. StackEngine is a zero-backend, pure Client-Side WASM utility. Drop your failing config into the sandbox above. We redact your secrets locally in the browser and auto-generate the refactored code using your own API key.


Prevention in CI/CD

1. Git — Enforce LF at the Repository Level

Add a .gitattributes file to your repo root:

# Force LF for all shell scripts committed to the repo
*.sh text eol=lf
Dockerfile text eol=lf

This prevents CRLF from ever being committed from a Windows workstation.

2. Hadolint — Dockerfile Linter in CI

# .github/workflows/lint.yml
- name: Lint Dockerfile
  uses: hadolint/[email protected]
  with:
    dockerfile: Dockerfile

Hadolint rule DL4006 flags missing set -o pipefail and improper ENTRYPOINT forms.

3. Docker Build-Time Validation

Add a CI step that runs the container with --entrypoint overridden to validate the script exists and is executable before promoting the image:

docker build -t myapp:${GIT_SHA} .
docker run --rm --entrypoint sh myapp:${GIT_SHA} -c "
  test -x /entrypoint.sh || (echo 'entrypoint not executable' && exit 1)
  file /entrypoint.sh | grep -v CRLF || (echo 'CRLF detected' && exit 1)
"

4. OPA / Conftest Policy

# policy/docker.rego
package docker

deny[msg] {
  input.Entrypoint[_] == cmd
  not startswith(cmd, "/")
  msg := sprintf("ENTRYPOINT '%v' must use an absolute path", [cmd])
}

Run with conftest test Dockerfile in your pipeline to block non-absolute entrypoint declarations before they ever reach a registry.

Related Diagnostics

"Part of the Syntax Utility Matrix."

View all 153 Syntax Tools →