# Purpose of the `--init` Flag in `container run`: Signal Handling and Zombie Reaping

> Learn how the container run --init flag improves application stability by managing signals and zombie processes, essential for apps not built as Linux init systems.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-07-09

---

**The `--init` flag injects a lightweight init process as PID 1 that forwards signals and reaps zombie processes, solving critical issues when your application isn't designed to run as a Linux init system.**

When running workloads with the `apple/container` toolkit, your application typically executes as **PID 1** inside the container namespace unless you specify otherwise. The `--init` flag in `container run` addresses the architectural challenges that arise when your command must handle responsibilities traditionally reserved for system init processes.

## Why PID 1 Matters in Linux Containers

Linux reserves **PID 1** for the init system, assigning it unique responsibilities that typical applications don't manage. When you invoke `container run` without special options, your specified command runs directly as PID 1, forcing it to handle two critical operating system duties:

- **Signal forwarding** – Receiving and properly dispatching signals (such as `SIGTERM` and `SIGINT`) to child processes in the process tree.
- **Zombie process reaping** – Calling `wait()` on terminated child processes to prevent them from becoming defunct "zombie" processes that consume system resources.

Most applications aren't written to act as init systems. They may ignore signals or fail to reap orphans, leading to graceful shutdown failures or resource leaks according to [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md) in the repository.

## How `container run --init` Works

When you specify `--init`, the runtime prepends a **lightweight init process** (similar to Docker’s `tini`) in front of your command. This init binary becomes PID 1, while your actual application runs as a child process.

### Signal Forwarding

The injected init process automatically **forwards all received signals** to your application. This ensures that when you send stop signals from the host, they reach your application correctly, enabling graceful shutdowns. As implemented in `apple/container`, this happens entirely within the same user namespace as your container.

### Zombie Process Reaping

The init system monitors for orphaned child processes and automatically calls `wait()` on them. This prevents zombie buildup that would otherwise occur if your application spawned child processes without reaping them. The integration tests in [`Tests/IntegrationTests/Run/TestCLIRunCommand.swift`](https://github.com/apple/container/blob/main/Tests/IntegrationTests/Run/TestCLIRunCommand.swift) specifically verify that no zombie processes appear when `--init` is active.

## Practical Usage Examples

The [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md) file documents the complete CLI interface for these flags.

### Basic Usage with Default Init

For most applications, simply adding `--init` provides proper signal handling and process management without additional configuration:

```bash

# Run with the default init process

container run --init ubuntu:latest my-app

```

You can also use it with `container create` for explicit container management:

```bash
container create --init --name my-container ubuntu:latest my-app

```

### Custom Init Images with `--init-image`

When you need to customize the init environment—such as running additional VM-level daemons or applying eBPF filters—pair `--init` with `--init-image`:

```bash
container run \
    --init-image local/custom-init:latest \
    alpine:latest \
    echo "hello from a container with a custom init"

```

The default init image is used when `--init` is specified alone, but `--init-image` allows providing a custom init filesystem image as detailed in [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md).

## Implementation and Testing Details

The `apple/container` repository includes comprehensive integration tests validating init process behavior. The file [`Tests/IntegrationTests/Run/TestCLIRunCommand.swift`](https://github.com/apple/container/blob/main/Tests/IntegrationTests/Run/TestCLIRunCommand.swift) contains tests verifying signal forwarding and zombie prevention, while [`Tests/IntegrationTests/Run/TestCLIRunInitImage.swift`](https://github.com/apple/container/blob/main/Tests/IntegrationTests/Run/TestCLIRunInitImage.swift) handles error cases and edge conditions for custom init images.

Because the init process runs in the same user namespace as your container, it adds **virtually no overhead** while guaranteeing correct signal propagation and process cleanup.

## Summary

- The `--init` flag solves the signal handling and zombie reaping problems inherent to running applications as PID 1 in `container run`.
- Without `--init`, your application must handle Linux init responsibilities itself, which most applications aren't designed to do.
- You can customize the init environment using `--init-image <image>` alongside `--init` for specialized use cases like VM-level daemons.
- The implementation is validated by integration tests in [`Tests/IntegrationTests/Run/TestCLIRunCommand.swift`](https://github.com/apple/container/blob/main/Tests/IntegrationTests/Run/TestCLIRunCommand.swift) that confirm proper process cleanup.

## Frequently Asked Questions

### What happens if I run a container without `--init`?

Your application runs directly as PID 1 and must handle signal forwarding and zombie reaping itself. If your application isn't designed as an init system, it may ignore shutdown signals or accumulate zombie processes, causing resource leaks and preventing graceful termination.

### Can I use a custom init binary instead of the default?

Yes. Use the `--init-image` flag to specify a custom filesystem image containing your init binary. This runs instead of the default init while still providing the PID 1 infrastructure. The [`Tests/IntegrationTests/Run/TestCLIRunInitImage.swift`](https://github.com/apple/container/blob/main/Tests/IntegrationTests/Run/TestCLIRunInitImage.swift) file tests this functionality and its error handling paths.

### Does using `--init` impact container performance?

No. According to [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md), the init process operates within the same user namespace as your container and consumes negligible resources. It adds virtually no overhead while solving critical process management issues.

### When should I avoid using `--init`?

Avoid `--init` if your application is specifically designed to function as an init system (such as systemd or a custom init) and needs to maintain PID 1 status for its own process management logic. For standard applications, databases, and web servers, `--init` is recommended to ensure proper signal handling and cleanup.