How to Manage Persistent Volumes with Journaling Options in Apple Container

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, 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. 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

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:

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

Create a volume with a custom 128 MiB writeback journal:

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:

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:

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 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →