Exit code 1 Warning Docker & Kubernetes

Exit Code 1 (General Error) in Docker & Kubernetes

Verdict · 1 = application-defined failure (no signal)

Exit code 1 is the application's own generic failure. The process started and returned 1, or an uncaught exception was mapped to 1 by the runtime. It is not a signal and not 128+n, so the code alone says nothing; the first stack trace or validation error in the logs does.

Observed exit1
Signal / meaningGeneral Error
Default actionWarning

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}'

Application log

kubectl logs <pod_name> --previous --tail=200

If .State.ExitCode is 1 and .State.OOMKilled is false, the kernel did not kill the process. That single fact separates this page from 137 (OOM/SIGKILL) and 139 (SIGSEGV). The next step is always the application's own first error line.

Three production root causes

The application ran and failed by its own rules. Look at docker logs or kubectl logs --previous for the first error, then check configuration, environment variables and mounted secrets. The status is intentionally generic and shared by many runtime failures.

1. Uncaught exception or failed assertion at startup

A Python traceback, a Java stack trace, a Node unhandled rejection or a failed config assertion typically ends the process with status 1. The container starts, reaches initialization and then calls exit(1). Search logs for the first traceback, not the last restart banner.

2. Missing or malformed environment variable or secret

Applications commonly validate DATABASE_URL, JWT_SECRET or API keys at boot. In Kubernetes a missing key in a Secret referenced with a non-optional env entry prevents the container from starting at all; a present but empty value passes the mount and fails application validation with exit 1. Compare kubectl exec env with the expected schema.

3. A shell wrapper propagated a child failure

With set -e, a failing command ends the script with that command's status, often 1. The real cause can be a curl health check, a migration command or a chown that fails because the user lacks permission. Run the entrypoint with sh -x locally or restore the failing command's stderr.

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.

Compose

docker-compose.yml

restart: on-failure:3 stops an immediate restart storm while preserving a few retries for a transient dependency. Do not use always here: a deterministic configuration error will restart forever and hide the first failure.

services:
  app:
    image: ghcr.io/acme/app:1.4.2
    restart: on-failure:3
    stop_grace_period: 20s
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M
Kubernetes

deployment.yaml

A crash loop with exit 1 is usually a configuration problem. Use kubectl logs --previous after the first restart, and check whether a Secret key exists before blaming the image. The liveness probe here prevents a half-started process from staying in the endpoint pool.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      terminationGracePeriodSeconds: 30
      containers:
        - name: app
          image: ghcr.io/acme/app:1.4.2
          resources:
            requests:
              cpu: "250m"
              memory: "256Mi"
            limits:
              cpu: "1000m"
              memory: "512Mi"
          env:
            - name: LOG_LEVEL
              value: "info"
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 20
            periodSeconds: 10
            failureThreshold: 3

Frequently asked questions

How do I find the real reason for exit code 1?

Read the first error in docker logs or kubectl logs --previous, not the restart summary. Then verify the exact command and args the container runs, the environment variables and mounted secrets, and whether a shell wrapper used set -e. The exit code itself carries no more information.

Is exit code 1 the same as a container crash?

It is a clean process failure, not a kernel kill. The process ran and returned status 1. A crash caused by a signal would be 128+n, for example 137 for SIGKILL or 139 for SIGSEGV. Kubernetes may still label the pod CrashLoopBackOff because it restarts repeatedly.

Why does exit code 1 happen only in Kubernetes and not locally?

The usual differences are configuration: missing Secret or ConfigMap keys, a read-only root filesystem, a different user ID, or a DNS/service name that only exists inside the cluster. Compare the deployed env and mounts with the local compose file before changing application code.

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