How to Create and Manage Persistent Volumes with Journaling in Apple Container
Apple Container stores volume data under a dedicated resource root directory and supports EXT4 journaling modes through the VolumesService API by passing journal driver options when creating volumes.
The apple/container repository provides a native container runtime with persistent storage capabilities. Each volume is backed by a disk image that survives container restarts and system reboots, with optional EXT4 journaling configurations that control data durability and performance characteristics.
Volume Configuration and Storage Architecture
Persistent volumes in Apple Container are represented by VolumeConfiguration records defined in Sources/ContainerResource/Volume/VolumeConfiguration.swift. These records store the volume’s name, driver, filesystem format, host-side source path, creation timestamp, labels, driver-specific options, and optional size limits.
Volume data resides under a resource root directory, typically /var/lib/container, where each volume receives a dedicated subdirectory containing the backing disk image. The path follows the convention /var/lib/container/volumes/<name>/volume.img, ensuring that data persists across system restarts.
Creating Journaled Volumes with VolumesService
The VolumesService class in Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift handles the complete volume lifecycle. When creating a volume, the service exposes the create(name:driverOpts:labels:) method, which internally calls _create(name:driver:driverOpts:labels:) to instantiate the storage.
To configure journaling, pass a journal key in the driverOpts dictionary. The service invokes parseJournalConfig(_:) to translate the option string into an EXT4.JournalConfig instance. This configuration is then passed to createVolumeImage(for:name:sizeInBytes:journal:), which formats the backing image with the specified journaling parameters.
Supported Journaling Modes
The journal driver option accepts the following EXT4 journaling modes. The parser expects strings in the format "<mode>" or "<mode>:<size>", where size suffixes support k, m, g, and t (binary units).
journal– Default EXT4 journaling using ordered mode.ordered– Metadata commits only after data writes flush to disk, providing consistency without full data journaling.writeback– No ordering guarantees between data and metadata writes, offering maximum performance.writeback:<size>– Writeback mode with an explicit journal size (e.g.,writeback:64m).none– Disables journaling entirely; attempting to use this mode will cause an error.
If the size component is omitted, Apple Container applies a default journal size defined in the EXT4 module.
Swift API Implementation
Use the VolumesService API to programmatically create and inspect journaled volumes.
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
)
// Create a volume with writeback journaling and 64 MiB journal size
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)")
Inspect existing volumes to verify journaling configuration:
let info = try await volumesService.inspect("my-data-volume")
print("Journal mode:", info.options["journal"] ?? "none")
print("Size:", info.sizeInBytes ?? 0)
List all volumes to audit their journaling settings:
let all = try await volumesService.list()
for v in all {
print("\(v.name) – driver: \(v.driver) – journal: \(v.options["journal"] ?? "default")")
}
CLI Usage Examples
Create volumes directly from the command line using the --opt flag to specify journaling behavior.
Create a volume with ordered journaling:
container volume create \
--opt journal=ordered \
my-ordered-volume
Create a volume with a custom journal size:
container volume create \
--opt journal=writeback:128m \
large-writeback-volume
Summary
- Apple Container stores persistent volumes under
/var/lib/container/volumes/<name>/with disk images created byVolumesService. - The
journaldriver option inSources/Services/ContainerAPIService/Server/Volumes/VolumesService.swiftsupportsordered,writeback, andwriteback:<size>modes. VolumeConfigurationinSources/ContainerResource/Volume/VolumeConfiguration.swifttracks volume metadata including journaling options.- Volume images survive container restarts and system reboots, maintaining data persistence across the runtime lifecycle.
Frequently Asked Questions
What happens if I specify an invalid journaling mode?
The parseJournalConfig(_:) method in VolumesService validates the option string against supported EXT4 modes. If you pass an unsupported value like none or malformed syntax, the service throws a validation error before creating the volume image.
Where does Apple Container store the actual volume data?
The backing disk image resides at /var/lib/container/volumes/<name>/volume.img by default, where <name> is the volume identifier. This location is determined by the resourceRoot parameter passed to VolumesService during initialization.
Can I change the journal mode after creating a volume?
No, the journaling configuration is written during initial volume creation via createVolumeImage(for:name:sizeInBytes:journal:). To change modes, you must create a new volume with the desired journal option and migrate data from the existing volume.
What is the difference between ordered and writeback journaling?
ordered mode guarantees that data writes flush to disk before metadata commits, preventing filesystem corruption while offering better performance than full journaling. writeback mode provides no ordering guarantees, maximizing throughput but risking metadata inconsistency if the system crashes before data writes complete.
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 →