# Handling tmpfs Mounts and Read-Only Root Filesystems in Apple Container

> Secure containers with Apple Container's read-only root filesystem and tmpfs mounts. Learn to implement enhanced security using --read-only and --tmpfs flags.

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

---

**Apple Container hardens container security by supporting read-only root filesystems via the `--read-only` flag and ephemeral tmpfs mounts via `--tmpfs`, implemented through the `ContainerConfiguration` struct and parsed in [`Flags.swift`](https://github.com/apple/container/blob/main/Flags.swift) and [`Parser.swift`](https://github.com/apple/container/blob/main/Parser.swift).**

The `apple/container` repository provides robust mechanisms for handling tmpfs mounts and read-only root filesystems in containers, allowing developers to secure workloads by preventing write access to base image layers while providing writable in-memory spaces for temporary data.

## Read-Only Root Filesystems

### CLI Flag and Configuration

The `--read-only` flag is defined in [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift) at line 319. When users invoke this flag, the CLI parser sets `management.readOnly` to `true`, which signals the runtime to mount the container's root filesystem as read-only.

### Implementation Pipeline

In [`Sources/Services/ContainerAPIService/Client/Utility.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Utility.swift) at line 255, the boolean value is copied into `config.readOnly` from the management configuration. This property is defined in [`Sources/ContainerResource/Container/ContainerConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/ContainerConfiguration.swift) at line 53. When the sandbox initializes, the runtime checks `ContainerConfiguration.readOnly`, and if `true`, mounts the rootfs with the `ro` flag, effectively passing `--read-only` to the underlying OCI runtime.

### Validation

The unit test `TestCLIRunCommand.testRunCommandReadOnly` in [`Tests/CLITests/Subcommands/Run/TestCLIRunCommand.swift`](https://github.com/apple/container/blob/main/Tests/CLITests/Subcommands/Run/TestCLIRunCommand.swift) at line 998 validates this behavior by attempting to create a file inside the container and expecting a permission error.

## Tmpfs Mounts

### Parsing the --tmpfs Flag

The `--tmpfs` flag is defined in [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift) at line 337, accepting arguments in the format `--tmpfs /run:size=64M,mode=1777`. The parser method `tmpfsMounts` in [`Sources/Services/ContainerAPIService/Client/Parser.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Parser.swift) (lines 332-340) processes these arguments, validates the mount specifications, and returns a deduplicated array of tmpfs configurations.

### Filesystem Object Construction

Each tmpfs mount is converted to a `Filesystem.tmpfs` object via the factory method in [`Sources/ContainerResource/Container/Filesystem.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/Filesystem.swift) at lines 28-34. This implementation sets `type = .tmpfs`, `source = "tmpfs"`, and stores the destination path along with any provided options in the `ContainerConfiguration.mounts` array.

### Mount Options

The `Parser.mount` method handles `size` and `mode` directives (around lines 13-30 in [`Parser.swift`](https://github.com/apple/container/blob/main/Parser.swift)), translating these into `-o size=…,mode=…` flags when the runtime mounts the filesystem during sandbox startup.

## Practical Examples

### Running with a Read-Only Rootfs

```bash
container run --read-only -it ubuntu:latest /bin/bash

```

The container's root filesystem mounts as `ro`. Any attempt to modify files in `/` will fail, as validated by the test suite.

### Adding a Tmpfs Mount

```bash

# Mount a 64 MiB tmpfs at /run with mode 1777

container run \
    --tmpfs /run:size=64M,mode=1777 \
    -it ubuntu:latest /bin/bash

```

Data written to `/run` persists only in memory and disappears when the container stops.

### Combining Both Flags

```bash
container run \
    --read-only \
    --tmpfs /tmp:size=128M \
    alpine:latest /bin/sh -c "echo hello > /tmp/hi && cat /tmp/hi"

```

The base image remains immutable while `/tmp` provides a writable in-memory area.

### Programmatic Configuration

```swift
import ContainerizationOCI
import Container

// Build a configuration programmatically
var cfg = ContainerConfiguration(
    id: "demo",
    image: ImageDescription(name: "ubuntu:latest"),
    process: ProcessConfiguration(command: ["/bin/bash"])
)
cfg.readOnly = true               // Read-only rootfs
cfg.mounts.append(.tmpfs(
    destination: "/run",
    options: ["size=64M", "mode=1777"]
))

// Pass `cfg` to the runtime (ContainerAPIService)

```

## Summary

- **Read-only rootfs**: Set via `--read-only` in [`Flags.swift`](https://github.com/apple/container/blob/main/Flags.swift), stored in `ContainerConfiguration.readOnly`, and enforced by the OCI runtime with the `ro` mount flag.
- **Tmpfs mounts**: Created via `--tmpfs` in [`Flags.swift`](https://github.com/apple/container/blob/main/Flags.swift), parsed by `Parser.tmpfsMounts`, and constructed as `Filesystem.tmpfs` objects in [`Filesystem.swift`](https://github.com/apple/container/blob/main/Filesystem.swift).
- **Validation**: The `TestCLIRunCommand.testRunCommandReadOnly` test verifies that write operations fail on read-only root filesystems.
- **Programmatic access**: Both features can be configured directly through `ContainerConfiguration` in Swift code.

## Frequently Asked Questions

### What is a read-only root filesystem in Apple Container?

A read-only root filesystem is a security feature that mounts the container's base image layers as read-only, preventing any modifications to the root filesystem. According to the source code in [`Sources/ContainerResource/Container/ContainerConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/ContainerConfiguration.swift), this is controlled by the `readOnly` boolean property, which when set to `true`, instructs the OCI runtime to apply the `ro` mount flag to the rootfs.

### How do tmpfs mounts work in Apple Container?

Tmpfs mounts create ephemeral, in-memory filesystems that exist only for the duration of the container's lifecycle. As implemented in [`Sources/ContainerResource/Container/Filesystem.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/Filesystem.swift), the `Filesystem.tmpfs` factory creates mount objects with `type = .tmpfs` and `source = "tmpfs"`, allowing the runtime to mount memory-based storage at specified destinations like `/tmp` or `/run`.

### Can I combine read-only rootfs with tmpfs mounts?

Yes, combining `--read-only` with `--tmpfs` flags provides a hardened security posture where the base image is immutable but specific paths remain writable. This pattern is common for running stateless applications where you need temporary writable space for caches or runtime data while ensuring the application binaries cannot be modified.

### What are the performance implications of using tmpfs?

Tmpfs mounts provide fast, in-memory I/O since they avoid disk writes, but they consume RAM from the host system. The `size` option (parsed in [`Parser.swift`](https://github.com/apple/container/blob/main/Parser.swift)) limits memory consumption, while the `mode` option sets Unix permissions. Data stored in tmpfs is lost when the container stops, making it suitable for temporary data only.