Containers Advanced

Troubleshooting Docker Container Exit Code 139 (Segmentation Fault) on Windows WSL2 Ubuntu

Diagnose and resolve Docker container crashes with exit code 139 (segmentation fault) running on WSL2 Ubuntu, a critical guide for developers and sysadmins.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Diagnose and resolve Docker container crashes with exit code 139 (segmentation fault) running on WSL2 Ubuntu, a critical guide for developers and sysadmins.

A Docker container exiting with code 139, often accompanied by a "segmentation fault" message, signifies a critical error where the container's main process attempted to access a memory location that it was not allowed to. This usually points to a fundamental issue within the application running inside the container or, less commonly, an underlying problem with the environment, such as resource constraints or library mismatches within your WSL2 Ubuntu setup. This guide provides a comprehensive approach to diagnosing and resolving these challenging errors.

Symptom & Error Signature

When a Docker container encounters a segmentation fault, it will abruptly terminate. You'll typically observe the following indicators:

  1. docker ps -a output: The container will show an Exited (139) status.

    root@your-wsl-ubuntu:~# docker ps -a
    CONTAINER ID   IMAGE                COMMAND                  CREATED         STATUS                      PORTS     NAMES
    a1b2c3d4e5f6   my-app:latest        "python app.py"          2 minutes ago   Exited (139) 1 minute ago             my-app-container
    
  2. docker logs <container_id> output: The logs will often explicitly state "segmentation fault" or "core dumped" just before termination.

    root@your-wsl-ubuntu:~# docker logs a1b2c3d4e5f6
    Initializing application...
    Loading configuration...
    Segmentation fault (core dumped)
    

    Depending on the application and its logging configuration, you might see a more detailed stack trace or an application-specific crash report preceding the segmentation fault message.

Root Cause Analysis

A segmentation fault (SIGSEGV) occurs when a program tries to access a memory address outside of its allocated memory space, or tries to access it in a way that is not allowed (e.g., writing to a read-only location). In the context of Docker containers running on WSL2 Ubuntu, the underlying reasons can be multifaceted:

  1. Application Bugs (Most Common):

    • Dangling Pointers/Null Pointers: Attempting to dereference a pointer that is null or points to freed memory.
    • Buffer Overflows/Underflows: Writing data beyond the boundaries of an array or buffer, corrupting adjacent memory.
    • Stack Overflows: Recursive functions or excessively large local variables consuming all available stack space.
    • Use-After-Free Errors: Accessing memory after it has been deallocated.
    • Double-Free Errors: Attempting to deallocate the same memory twice. These are typically problems in native code (C/C++, Rust) or language runtimes with C extensions (Python, Node.js, Ruby, PHP).
  2. Memory Corruption/Resource Exhaustion:

    • While distinct from a direct OOM (Out Of Memory) error (which often results in exit code 137), severe memory pressure or incorrect memory management can sometimes lead to a segfault. If the system (WSL2 or container) runs out of available memory, the program might try to access invalid memory regions, resulting in a segfault.
    • Incorrectly configured container memory limits (-m) can starve the application.
  3. Library Mismatch or Corruption:

    • GLibC/Musl issues: If your application is built against a specific C standard library (e.g., GNU C Library – glibc) and attempts to run in a container environment using a different one (e.g., Alpine's Musl libc) without proper recompilation or linking, compatibility issues can arise.
    • Incorrectly linked shared libraries: The container might be missing a required shared library or linking to an incompatible version, leading to memory access errors during runtime.
  4. Corrupted Container Image or Host FS Issues:

    • Though rare, a corrupted Docker image layer or underlying filesystem corruption on the WSL2 instance itself could potentially lead to malformed binaries or libraries that cause segfaults.
  5. WSL2-Specific Quirks (Less Common):

    • Highly optimized or low-level applications might occasionally expose subtle bugs or unusual interactions with the WSL2 kernel environment. This is less common but worth considering if all other avenues are exhausted.

Step-by-Step Resolution

Troubleshooting segmentation faults requires a systematic approach, often starting with the application itself.

1. Identify the Failing Process and Review Logs Thoroughly

Begin by using docker ps -a to confirm the container's status and docker logs to retrieve all available output. Look for any messages before the "segmentation fault" that might indicate the last action taken by the application. This is your primary clue.

# Check all containers, find the one with Exited (139)
docker ps -a

# Get detailed logs for the identified container
docker logs <CONTAINER_ID_OR_NAME>

Pay close attention to the exact point of failure in the logs. If the crash occurs immediately on startup, it suggests an initialization issue or a fundamental problem with the application's environment or dependencies. If it happens after some runtime, it's likely triggered by a specific code path or data input.

2. Debug the Application with a Debugger (GDB)

The most effective way to pinpoint a segmentation fault in native code is by using a debugger like GDB. This requires building your application with debugging symbols and potentially adjusting container security.

  1. Build with Debugging Symbols: Ensure your application (or the problematic library) is compiled with -g flag for C/C++ (or equivalent for other native languages) to include debugging information.

  2. Run Container with Debugger Privileges: You need to grant the container SYS_PTRACE capability and disable seccomp restrictions to allow GDB to attach to and inspect processes.

    docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -it --rm <YOUR_IMAGE_NAME> /bin/bash
    

    Replace <YOUR_IMAGE_NAME> with your actual image. This command starts an interactive bash shell within the container with necessary privileges.

  3. Install GDB (if not present): Inside the container, if GDB is not already installed:

    apt update && apt install -y gdb
    
  4. Run your application under GDB: Navigate to your application's directory and run it with GDB.

    gdb /path/to/your/app
    (gdb) run
    

    Once the segfault occurs, GDB will break.

  5. Get a Backtrace: At the GDB prompt, type bt (backtrace) to see the call stack leading up to the crash. This is crucial for identifying the exact line of code or function causing the issue.

    (gdb) bt
    #0  0x0000555555555123 in problematic_function (arg=0x0) at src/main.c:42
    #1  0x00005555555551a0 in another_function () at src/main.c:55
    #2  0x000055555555520a in main (argc=1, argv=0x7fffffffdfc8) at src/main.c:60
    

    This output tells you the function (problematic_function), file (src/main.c), and line number (42) where the segmentation fault occurred.

Running containers with SYS_PTRACE and seccomp=unconfined significantly lowers their security posture. Only use this for debugging purposes and never in production environments.

3. Check Container Resource Limits

Insufficient memory can sometimes lead to unexpected behavior and segmentation faults, although OOM errors are usually exit 137.

  1. Inspect current container limits:

    docker inspect <CONTAINER_ID_OR_NAME> | grep -E "Memory|Cpu"
    
  2. Run with explicit memory limits: Test if increasing memory resolves the issue.

    docker run -m 4GB <YOUR_IMAGE_NAME>
    

    Try different values (e.g., -m 2GB, -m 8GB).

  3. Adjust WSL2 Memory Limits: If the host WSL2 instance itself is running low on memory, it can affect containers. Modify your .wslconfig file. Create or edit C:Users<YourUser>.wslconfig.

    # C:Users<YourUser>.wslconfig
    [wsl2]
    memory=8GB            # Sets the maximum memory WSL2 can use to 8GB
    processors=4          # Sets the number of virtual processors WSL2 can use
    swap=2GB              # Sets the amount of swap space
    localhostforwarding=true
    

    After modifying .wslconfig, you must shut down WSL2 completely for changes to take effect: wsl --shutdown in PowerShell or Command Prompt. Then restart your Ubuntu instance.

4. Update Docker, WSL2, and Ubuntu

Ensure all components of your environment are up-to-date. This can fix known bugs or compatibility issues.

  1. Update WSL2 components (from PowerShell/CMD):

    wsl --update
    wsl --version # Verify the kernel version
    
  2. Update Ubuntu packages (from within your WSL2 Ubuntu instance):

    sudo apt update && sudo apt upgrade -y
    sudo apt dist-upgrade -y # For significant version changes
    
  3. Update Docker Desktop: Ensure your Docker Desktop application on Windows is running the latest stable version. Check for updates via the Docker Desktop settings or official website.

5. Verify Library Compatibility and Base Image

A common source of segfaults in containers is an incompatible library.

  1. Check Base Image: If your Dockerfile uses a very minimal base image (e.g., alpine), consider temporarily switching to a more feature-rich Debian-based image (e.g., ubuntu:latest, debian:stable). Alpine uses Musl libc, while most other distributions use GLibC, and some native binaries compiled for GLibC may fail on Musl.

    # Example: Switch base image
    FROM ubuntu:22.04
    # ... rest of your Dockerfile
    
  2. Inspect Shared Libraries: Inside your running container (or a temporary one created from your image), you can use ldd to list dynamic library dependencies of your executable. This helps identify if a library is missing or unexpectedly linked.

    # Example for Python:
    docker run -it --rm <YOUR_IMAGE_NAME> /bin/bash
    # Inside container:
    ldd /usr/bin/python3.10 # Or path to your specific binary
    

    Look for not found errors or unusual library paths.

6. Rebuild/Re-pull Docker Image with --no-cache

Sometimes a corrupted or stale cache can lead to issues. Forcing a full rebuild ensures all layers are fresh.

  1. Rebuild your image:

    docker build --no-cache -t <YOUR_IMAGE_NAME> .
    
  2. Re-pull external images: If you're using a public image, try pulling it again to ensure you have the latest and uncorrupted version.

    docker pull <IMAGE_NAME>:<TAG>
    

Using docker builder prune -a can delete a significant amount of cached data, potentially slowing down subsequent builds. Use with caution and only if -no-cache doesn't resolve the issue and you suspect a deeper build cache corruption.

7. Reproduce in a Minimal Environment (Isolation)

If the segfault is elusive, try to strip down your application and its environment to the bare minimum to isolate the problem.

  1. Minimal Dockerfile: Create a new Dockerfile that only installs your application's direct dependencies and runs the failing part of the code.
  2. Minimal data: Use a very small dataset or simple input if the application processes data.
  3. Remove non-essential services: If your container runs multiple services (e.g., Nginx, PHP-FPM, Redis), isolate the one that's crashing.

By following these steps, you should be able to systematically diagnose and resolve the "Docker container exited with code 139 segmentation fault" error, restoring stability to your WSL2-based containerized applications.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.