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 metadataordered– Ext4 ordered mode where writes are flushed before metadata commitswriteback– Ext4 writeback mode with no ordering guaranteeswriteback:<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
VolumeConfigurationrecords and persists data under/var/lib/container/volumes/<name>/volume.img. - The
VolumesService.parseJournalConfig(_:)method inSources/Services/ContainerAPIService/Server/Volumes/VolumesService.swiftprocessesjournaldriver options. - Supported modes include
journal,ordered,writeback, andwriteback:<size>with binary size suffixes (k,m,g,t). - The
_createmethod invokescreateVolumeImage(for:name:sizeInBytes:journal:)to write theEXT4.JournalConfiginto the backing image. - You can configure journaling via the Swift API's
driverOptsparameter 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →