# How Apple Container Implements Read‑Only Root Filesystems and tmpfs Mounts

> Discover how Apple Container implements read-only root filesystems and tmpfs mounts by translating CLI flags to OCI specs and using the Linux kernel via runc-compatible runtimes.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: internals
- Published: 2026-07-02

---

**Apple Container enables read‑only root filesystems and tmpfs mounts by translating CLI flags into OCI runtime specifications, delegating actual mount operations to the Linux kernel through runc‑compatible runtimes.**

Apple Container is a Swift‑based container runtime developed by Apple that constructs OCI‑compliant container specifications for Linux environments. Understanding how it handles read‑only root filesystems and tmpfs mounts requires tracing the path from CLI argument parsing through the configuration model to the final runtime execution in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift).

## CLI Flag Parsing for Read‑Only and tmpfs Options

The implementation begins at the command line interface, where two distinct flags control these features.

In [`Sources/Services/ContainerAPIService/Client/Flags.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Flags.swift), the tool defines:

- **`@Flag(name: .long)`** for `--read‑only` (or `-r`), which mounts the container's root filesystem as read‑only
- **`@Option(name: .customLong("tmpfs"))`** for `--tmpfs <path>`, which adds a tmpfs mount at the specified container path

These values are stored in a `ContainerManagement` struct that merges into the final `ContainerConfiguration`.

## Read‑Only Root Filesystem Implementation

### Configuration Storage

The `ContainerConfiguration` struct in [`Sources/ContainerResource/Container/ContainerConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/ContainerConfiguration.swift) contains a `readOnly: Bool` property. When the `--read‑only` flag is present, this Boolean is set to `true` and persisted in the container's configuration state.

### OCI Runtime Translation

When the container launches, [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) assembles the OCI specification. If `configuration.readOnly` is `true`, the runtime sets the OCI `root.readonly` field to `true`, producing JSON similar to:

```json
"root": {
    "path": "/path/to/rootfs",
    "readonly": true
}

```

The OCI runtime (such as runc) then mounts the root filesystem with the `MS_RDONLY` kernel flag. Any write operation to the root filesystem (for example, `touch /newfile`) fails with the `EROFS` (Read‑only filesystem) error.

## tmpfs Mount Implementation

### Parsing Arguments into Filesystem Objects

The `--tmpfs` flag is processed by `Parser.tmpfsMounts(_:)` in [`Sources/Services/ContainerAPIService/Client/Parser.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Parser.swift) (lines 340‑353). This method converts each supplied path into a `Filesystem` object of type `.tmpfs`.

### Filesystem Model Definition

The `Filesystem` enum in [`Sources/ContainerResource/Container/Filesystem.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Container/Filesystem.swift) defines the `.tmpfs` case with a static constructor `Filesystem.tmpfs(destination:options:)`. This constructor automatically sets `source: "tmpfs"` and `type: .tmpfs`, creating a complete mount specification that is appended to `ContainerConfiguration.mounts`.

### Runtime Integration

In [`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) (lines 1344‑1349), the mount list is iterated during container creation. For each entry where `type == .tmpfs`, the runtime emits an OCI mount entry:

```json
{
    "destination": "/tmp",
    "type": "tmpfs",
    "source": "tmpfs",
    "options": []
}

```

The Linux kernel creates an anonymous `tmpfs` filesystem at the specified mount point. This in‑memory filesystem is writable during the container's lifetime but disappears completely when the container exits, never touching the underlying host storage.

## Practical Usage Examples

The following Swift code demonstrates how to invoke these features via the Apple Container API:

```swift
// Enable a read-only root filesystem
let runArgs = ["--read-only"]
try container.run(name: "demo", image: "ubuntu:22.04", args: runArgs)

```

```swift
// Add a tmpfs mount at /tmp
let runArgs = ["--tmpfs", "/tmp"]
try container.run(name: "demo", image: "ubuntu:22.04", args: runArgs)

```

```swift
// Combine both for a read-only base with writable scratch space
let runArgs = ["--read-only", "--tmpfs", "/tmp", "--tmpfs", "/var/cache"]
try container.run(name: "demo", image: "ubuntu:22.04", args: runArgs)

```

## Summary

- **Apple Container** delegates mount operations to the OCI runtime by constructing compliant specifications in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift).
- **Read‑only roots** are enforced via the OCI `root.readonly` field, which triggers the `MS_RDONLY` kernel flag.
- **tmpfs mounts** are defined in [`Filesystem.swift`](https://github.com/apple/container/blob/main/Filesystem.swift) and parsed via `Parser.tmpfsMounts()`, resulting in anonymous memory filesystems that vanish on container exit.
- Both features can be combined to create secure, ephemeral container environments with immutable base images and temporary writable overlays.

## Frequently Asked Questions

### How do I enable a read‑only root filesystem in Apple Container?

Use the `--read‑only` or `-r` flag when running a container. This sets `ContainerConfiguration.readOnly` to `true`, which translates to the OCI `root.readonly` field and ultimately mounts the root filesystem with kernel‑level read‑only protection.

### Where does Apple Container store tmpfs mount configurations?

tmpfs mounts are stored in the `mounts: [Filesystem]` array within [`ContainerConfiguration.swift`](https://github.com/apple/container/blob/main/ContainerConfiguration.swift). Each mount is represented as a `Filesystem.tmpfs` object created by `Parser.tmpfsMounts(_:)` in [`Parser.swift`](https://github.com/apple/container/blob/main/Parser.swift).

### What happens if I try to write to a read‑only root filesystem?

The kernel returns an `EROFS` (Read‑only filesystem) error. The OCI runtime configures the mount with the `MS_RDONLY` flag, preventing any write operations to the root filesystem regardless of user permissions.

### Can I use multiple tmpfs mounts with a read‑only root?

Yes. You can specify `--tmpfs` multiple times for different paths (for example, `--tmpfs /tmp --tmpfs /var/run`) simultaneously with `--read‑only`. This creates a secure configuration where the base image cannot be modified, but specific directories provide writable, ephemeral scratch space.