# How to Manage Persistent Volumes with Journaling Options in Apple Container

> Learn to manage persistent volumes with EXT4 journaling in Apple Container. Configure ordered, writeback, and custom journal sizes using the VolumesService API for robust data management.

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

---

**Apple Container enables EXT4 journaling configuration for persistent volumes through the `journal` driver option, supporting modes like `ordered`, `writeback`, and custom journal sizes via the `VolumesService` API.**

Apple Container provides a robust storage subsystem for managing persistent volumes with configurable EXT4 journaling options. When you create a volume using the `VolumesService`, you specify journaling modes through driver-specific options that control data durability and performance characteristics. This implementation leverages `VolumeConfiguration` records stored under a dedicated resource root to ensure volume metadata survives container restarts and system reboots.

## Understanding Volume Configuration and Storage Layout

In [`Sources/ContainerResource/Volume/VolumeConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Volume/VolumeConfiguration.swift), Apple Container defines the **`VolumeConfiguration`** data model that tracks each volume's metadata, including its name, driver, filesystem format, host-side source path, creation timestamp, labels, and driver-specific options.

Volume data persists under the container's **resource root** directory, typically `/var/lib/container/volumes/<name>/volume.img`. This path ensures that volumes remain available across container restarts because the backing image files reside on the host filesystem rather than inside ephemeral container layers.

## Configuring EXT4 Journaling Modes

The journaling configuration is handled by **`VolumesService`** in [`Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift). When creating a volume, you pass journaling preferences through the `driverOpts` dictionary using the `journal` key.

### Supported Journaling Options

The **`parseJournalConfig(_:)`** method supports the following modes:

- **`journal`** – Default EXT4 journaling with ordered metadata
- **`ordered`** – Ext4 ordered mode where writes are flushed before metadata commits
- **`writeback`** – Ext4 writeback mode with no ordering guarantees
- **`writeback:<size>`** – Writeback mode with explicit journal size (e.g., `writeback:64m`)
- **`none`** – Disables journaling (unsupported and will cause an error)

Size suffixes follow standard binary units: **`k`** (kilobytes), **`m`** (megabytes), **`g`** (gigabytes), and **`t`** (terabytes). If you omit the size, Apple Container uses the default journal size defined in `EXT4.JournalConfig`.

### Implementation Details

When you call the creation methods, `VolumesService` invokes the private **`_create(name:driver:driverOpts:labels:)`** method, which subsequently calls **`createVolumeImage(for:name:sizeInBytes:journal:)`**. The `journal` parameter receives the parsed `EXT4.JournalConfig` and writes the configuration directly into the disk image that backs the volume.

## Creating Journaled Volumes with VolumesService

You can create volumes programmatically using the Swift API or via the command line interface.

### Swift API Example

```swift
import Containerization
import ContainerPersistence
import Logging

let logger = Logger(label: "com.example.volumes")
let volumesService = try await VolumesService(
    resourceRoot: FilePath("/var/lib/container"),
    containersService: containersService,
    log: logger
)

let config = try await volumesService.create(
    name: "my-data-volume",
    driverOpts: ["journal": "writeback:64m"],
    labels: ["app": "my-service"]
)

print("Created volume \(config.name) at \(config.source)")

```

### CLI Examples

Create a volume with ordered journaling:

```bash
container volume create \
    --opt journal=ordered \
    my-ordered-volume

```

Create a volume with a custom 128 MiB writeback journal:

```bash
container volume create \
    --opt journal=writeback:128m \
    large-writeback-volume

```

## Inspecting and Listing Volumes

After creation, you can verify journaling configuration using the inspection methods provided by `VolumesService`.

To inspect a specific volume:

```swift
let info = try await volumesService.inspect("my-data-volume")
print("Journal mode:", info.options["journal"] ?? "none")
print("Size:", info.sizeInBytes ?? 0)

```

To list all volumes and their journaling status:

```swift
let all = try await volumesService.list()
for v in all {
    print("\(v.name) – driver: \(v.driver) – journal: \(v.options["journal"] ?? "default")")
}

```

## Summary

- Apple Container stores volume metadata in **`VolumeConfiguration`** records and persists data under `/var/lib/container/volumes/<name>/volume.img`.
- The **`VolumesService.parseJournalConfig(_:)`** method in [`Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift) processes `journal` driver options.
- Supported modes include **`journal`**, **`ordered`**, **`writeback`**, and **`writeback:<size>`** with binary size suffixes (`k`, `m`, `g`, `t`).
- The **`_create`** method invokes **`createVolumeImage(for:name:sizeInBytes:journal:)`** to write the `EXT4.JournalConfig` into the backing image.
- You can configure journaling via the Swift API's `driverOpts` parameter or the CLI **`--opt journal=<mode>`** flag.

## Frequently Asked Questions

### What happens if I specify an unsupported journaling mode?

Specifying `journal=none` or any invalid format triggers an error during volume creation because Apple Container requires journaling for data integrity. The `parseJournalConfig(_:)` method validates input strings against supported modes and rejects disallowed values before attempting to create the disk image.

### Can I change the journal mode after creating a volume?

No, the journaling mode is immutable once the volume image is created. The `createVolumeImage(for:name:sizeInBytes:journal:)` method writes the `EXT4.JournalConfig` into the backing image file at `/var/lib/container/volumes/<name>/volume.img` during initial creation. To use a different journaling mode, you must create a new volume and migrate your data.

### Where does Apple Container store volume configuration data?

Volume configuration data resides in the resource root directory, specifically within [`Sources/ContainerResource/Volume/VolumeConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Volume/VolumeConfiguration.swift). The actual disk images backing the volumes are stored at paths like `/var/lib/container/volumes/<name>/volume.img`, ensuring persistence across system reboots and container restarts.

### How do I specify journal size in the CLI?

Append the size to the mode using standard binary suffixes. For example, `journal=writeback:64m` creates a 64 MiB journal, while `journal=writeback:1g` creates a 1 GiB journal. Valid suffixes include `k`, `m`, `g`, and `t` for kilobytes, megabytes, gigabytes, and terabytes respectively.