How to fix Container process (PID 1) exited unexpectedly in Docker

DockerINTERMEDIATEHIGHUpdated Dec 1, 2025· 267 views

This error occurs when the main process running inside a Docker container (PID 1) terminates unexpectedly, causing the container to stop. The fix typically involves ensuring your application runs in the foreground, handles signals properly, and uses an init process when needed.

Quick fix

Fixes Container process (PID 1) exited unexpectedly

# View full logs from exited container
docker logs <container_name_or_id>

# View last 50 lines with timestamps
docker logs --tail 50 --timestamps <container_name_or_id>

# Follow logs in real-time (useful during debugging)
docker logs -f <container_name_or_id>
  1. Check container logs for error messages
  2. Inspect the container exit code and state
  3. Use exec form for CMD and ENTRYPOINT
  4. Ensure the process runs in foreground mode
docker — error
# View full logs from exited container
docker logs <container_name_or_id>
# View last 50 lines with timestamps
docker logs --tail 50 --timestamps <container_name_or_id>
# Follow logs in real-time (useful during debugging)
docker logs -f <container_name_or_id>
Container process (PID 1) exited unexpectedly

What this error means

In Docker, each container has a main process that runs as PID 1 (Process ID 1). Unlike traditional Linux systems where PID 1 is the init system (systemd, init, etc.), in containers PID 1 is your application itself. When this process exits for any reason, the entire container stops immediately. This error indicates that your container's main process terminated when it was expected to keep running. The container lifecycle is directly tied to this process - there is no background daemon keeping the container alive. If PID 1 exits with code 0, Docker considers it a successful completion. If it exits with any other code, Docker reports it as an unexpected exit. Understanding PID 1 behavior is crucial because it differs from regular processes: PID 1 has special signal handling rules in Linux. By default, signals like SIGTERM are ignored unless explicitly handled, which can cause issues with graceful shutdowns.

Typical symptoms

  • Container starts and immediately stops (exits within seconds)
  • docker ps shows container with status 'Exited' instead of 'Up'
  • docker logs shows the application starting but then nothing else
  • Container works with docker run -it but exits with docker run -d
  • Application logs indicate successful startup but container still exits
  • docker inspect shows ExitCode is non-zero (commonly 1, 137, or 139)
  • Container restarts repeatedly when using restart: always policy
  • docker stop takes exactly 10 seconds (timeout waiting for SIGTERM)

Common causes

  1. Main process completed its task and exited normally (not designed to run continuously)
  2. Application is running in background/daemon mode instead of foreground
  3. Shell script entrypoint exits after spawning a background process
  4. Application crashed due to an unhandled exception or error
  5. Process was killed by the kernel (OOM killer) due to memory limits
  6. Signal handling not configured - SIGTERM ignored because process is PID 1
  7. ENTRYPOINT or CMD misconfigured, causing wrong process to run as PID 1
  8. Shell form CMD runs /bin/sh as PID 1, which exits when child process completes
  9. Missing dependencies or configuration files causing immediate crash
  10. Segmentation fault or other critical runtime error

How to fix "Container process (PID 1) exited unexpectedly"

1Check container logs for error messages

First, examine what happened before the container exited. The logs often reveal the root cause:

bash
# View full logs from exited container
docker logs <container_name_or_id>

# View last 50 lines with timestamps
docker logs --tail 50 --timestamps <container_name_or_id>

# Follow logs in real-time (useful during debugging)
docker logs -f <container_name_or_id>

Look for error messages, stack traces, or any indication of why the process terminated. If the logs are empty, the process likely crashed before producing any output.

2Inspect the container exit code and state

The exit code provides valuable information about why the container stopped:

bash
# Get detailed container state including exit code
docker inspect --format='{{.State.ExitCode}} {{.State.Error}}' <container_id>

# Get full state information
docker inspect --format='{{json .State}}' <container_id> | jq

Common exit codes:
- 0: Process exited successfully (completed its task)
- 1: General application error
- 126: Command cannot execute (permission problem)
- 127: Command not found
- 137: Killed by SIGKILL (often OOM killer, exit code = 128 + 9)
- 139: Segmentation fault (exit code = 128 + 11)
- 143: Killed by SIGTERM (exit code = 128 + 15)

For OOM issues, also check:

bash
docker inspect --format='{{.State.OOMKilled}}' <container_id>
3Use exec form for CMD and ENTRYPOINT

One of the most common causes is using shell form instead of exec form for CMD or ENTRYPOINT. Shell form runs your command as a child of /bin/sh, which causes signal handling problems.

Incorrect (shell form):

dockerfile
CMD python app.py
# This runs: /bin/sh -c "python app.py"
# /bin/sh is PID 1, python is a child process

Correct (exec form):

dockerfile
CMD ["python", "app.py"]
# This runs: python app.py directly as PID 1
# Python receives signals directly

The exec form (JSON array syntax) ensures your application runs directly as PID 1, receiving signals properly. Always use exec form unless you specifically need shell features.

4Ensure the process runs in foreground mode

Many applications default to daemon mode, which backgrounds the process and causes the foreground process to exit. You must configure your application to run in the foreground.

Common examples:

dockerfile
# Nginx - use daemon off
CMD ["nginx", "-g", "daemon off;"]

# Apache httpd - use FOREGROUND
CMD ["httpd", "-D", "FOREGROUND"]

# PostgreSQL - runs in foreground by default
CMD ["postgres"]

# Redis - runs in foreground by default
CMD ["redis-server"]

# Node.js - runs in foreground by default
CMD ["node", "server.js"]

Avoid these patterns:

dockerfile
# BAD - backgrounds the process
CMD ["sh", "-c", "nginx &"]

# BAD - nohup often causes issues
CMD ["nohup", "python", "app.py"]
5Fix shell script entrypoints

If using a shell script as your entrypoint, ensure it keeps the main process in the foreground and properly handles the exec handoff:

Problematic entrypoint.sh:

bash
#!/bin/bash
# Setup tasks
echo "Starting application..."
python app.py &  # BAD: backgrounds the process
echo "Started"    # Script exits here, container stops

Fixed entrypoint.sh:

bash
#!/bin/bash
set -e

# Setup tasks (run before main process)
echo "Running initialization..."

# Use exec to replace shell with the main process
# Now python becomes PID 1 and receives signals directly
exec python app.py

The exec command replaces the shell process with your application, making it PID 1. Without exec, the shell remains PID 1 and your app runs as a child process.

6Use docker --init for proper signal handling

Docker's --init flag adds a tiny init process (tini) as PID 1, which properly forwards signals and reaps zombie processes:

bash
# Run container with init process
docker run --init -d myimage

# In docker-compose.yml
services:
  myapp:
    image: myimage
    init: true

This is especially useful when:
- Your application doesn't handle SIGTERM properly
- You're running multiple processes in a container
- You see zombie processes accumulating
- docker stop takes the full 10-second timeout

Alternatively, add tini to your Dockerfile:

dockerfile
# Install tini
RUN apt-get update && apt-get install -y tini

# Use tini as entrypoint
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["python", "app.py"]
7Add signal handling to your application

If you cannot use --init, implement signal handling in your application code:

Python example:

python
import signal
import sys

def handle_sigterm(signum, frame):
    print("Received SIGTERM, shutting down gracefully...")
    # Cleanup code here
    sys.exit(0)

signal.signal(signal.SIGTERM, handle_sigterm)
signal.signal(signal.SIGINT, handle_sigterm)

# Your main application code

Node.js example:

javascript
process.on('SIGTERM', () => {
  console.log('Received SIGTERM, shutting down gracefully...');
  // Cleanup code here
  process.exit(0);
});

process.on('SIGINT', () => {
  console.log('Received SIGINT, shutting down gracefully...');
  process.exit(0);
});

Bash script example:

bash
#!/bin/bash
trap 'echo "Caught SIGTERM"; exit 0' TERM
trap 'echo "Caught SIGINT"; exit 0' INT

# Your main logic here
while true; do
  # Do work
  sleep 1
done
8Debug by running container interactively

To investigate what's happening inside the container, run it interactively:

bash
# Override entrypoint to get a shell
docker run -it --entrypoint /bin/sh myimage

# Or /bin/bash if available
docker run -it --entrypoint /bin/bash myimage

# Once inside, manually run your application
./entrypoint.sh
# or
python app.py

This lets you:
- Check if required files exist
- Verify environment variables are set correctly
- Test the application startup manually
- See error messages that might not appear in logs

For containers that exit immediately:

bash
# Keep container running with tail
docker run -d myimage tail -f /dev/null

# Then exec into it
docker exec -it <container_id> /bin/sh
9Check for memory limits causing OOM kills

If your container is being killed by the OOM (Out of Memory) killer, you'll see exit code 137:

bash
# Check if container was OOM killed
docker inspect --format='{{.State.OOMKilled}}' <container_id>

# Check kernel logs for OOM messages (on the host)
dmesg | grep -i "killed process"

Solutions:

1. Increase memory limit:

bash
docker run -m 2g myimage

# docker-compose.yml
services:
  myapp:
    image: myimage
    deploy:
      resources:
        limits:
          memory: 2G

2. Optimize application memory usage

3. Add swap (not recommended for production):

bash
docker run -m 1g --memory-swap 2g myimage

Advanced notes

Understanding PID 1 in Linux vs Containers

In traditional Linux, PID 1 is the init system (systemd, SysV init) which has special kernel protections - it cannot be killed by signals unless it explicitly handles them. In containers, your application becomes PID 1, inheriting these protections. This means SIGTERM and SIGINT are ignored by default unless your application registers signal handlers.

The exec vs shell form behavior

When using shell form CMD command arg1 arg2, Docker actually runs /bin/sh -c "command arg1 arg2". This means:
1. /bin/sh is PID 1
2. Your command runs as a child process
3. Signals sent to the container go to /bin/sh first
4. Shell may not forward signals to child processes
5. When the shell exits, your process becomes orphaned

Multi-process containers

If you need multiple processes in a container (not recommended but sometimes necessary), use a proper process supervisor:

dockerfile
# Using supervisord
COPY supervisord.conf /etc/supervisor/conf.d/
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

# Using s6-overlay (Alpine-friendly)
ADD https://github.com/just-containers/s6-overlay/releases/download/v3.1.5.0/s6-overlay-noarch.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz
ENTRYPOINT ["/init"]

Debugging with strace

For mysterious exits, trace system calls:

bash
# Install strace in container, then:
docker run -it --cap-add SYS_PTRACE myimage strace -f -e trace=process python app.py

Health checks as early warning

Use Docker health checks to detect issues before complete failure:

dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

Frequently asked questions

What does "Container process (PID 1) exited unexpectedly" mean?
In Docker, each container has a main process that runs as PID 1 (Process ID 1). ), in containers PID 1 is your application itself. When this process exits for any reason, the entire container stops immediately.
How do I fix "Container process (PID 1) exited unexpectedly"?
This error occurs when the main process running inside a Docker container (PID 1) terminates unexpectedly, causing the container to stop. The fix typically involves ensuring your application runs in the foreground, handles signals properly, and uses an init process when needed.
What causes "Container process (PID 1) exited unexpectedly"?
Main process completed its task and exited normally (not designed to run continuously) Application is running in background/daemon mode instead of foreground Shell script entrypoint exits after spawning a background process
Is the "Container process (PID 1) exited unexpectedly" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading