# How to Use Container System Properties for Default Configurations in apple/container

> Learn to leverage container system properties in apple/container to customize default configurations for build, container, DNS, and registry settings. Override defaults easily.

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

---

**Container system properties in apple/container are defined in [`config.toml`](https://github.com/apple/container/blob/main/config.toml) and decoded into the `ContainerSystemConfig` class, allowing you to override hard-coded defaults for build, container, DNS, and registry settings without modifying source code.**

The `apple/container` repository provides a Swift-based containerization framework that relies on hierarchical configuration management. By leveraging container system properties, developers can customize default behaviors for virtual machine resources, network settings, and image registries through declarative TOML files rather than hard-coding values throughout the application.

## Understanding Container System Configuration

The configuration system reads global defaults from **[`config.toml`](https://github.com/apple/container/blob/main/config.toml)** files and decodes them into the `ContainerSystemConfig` struct defined in [`Sources/ContainerPersistence/ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ContainerSystemConfig.swift). This approach separates environment-specific settings from application logic, enabling portable deployments across development machines and CI pipelines.

### Configuration Hierarchy and Loading Order

The framework implements a layer-by-layer loading strategy that merges configuration files in precedence order. Files are read from user-provided paths, system-wide directories, and bundled defaults, with later values overriding earlier ones. Any missing key falls back to the struct’s initialization-time defaults, ensuring the system remains functional even with partial configuration files.

### Default Values and Fallback Behavior

When the TOML decoder encounters missing fields, it automatically substitutes hard-coded defaults defined directly in the Swift structs. These defaults cover critical runtime parameters:

- **Build settings**: Rosetta emulation (`true`), CPU count (`2`), memory (`2048mb`), and builder image references
- **Container resources**: CPU allocation (`4`) and memory limits (`1g`) for new containers
- **Network configuration**: Optional DNS domains and subnet allocations
- **Kernel binaries**: Path mappings and remote URLs for Kata Containers kernels
- **Registry endpoints**: Default domain (`docker.io`) for unqualified image references

## Loading Container System Properties Programmatically

Access container system properties in your Swift code using the asynchronous loading methods provided by the framework.

### Using the Application Helper

The recommended entry point for CLI commands resides in [`Sources/ContainerCommands/Application.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Application.swift):

```swift
import ContainerPersistence

let systemConfig = try await Application.loadContainerSystemConfig()

```

This method handles file discovery, validation, and decoding automatically, returning a fully populated `ContainerSystemConfig` instance.

### Direct Configuration Loading

For specialized use cases or custom command implementations, access the loader directly from [`Sources/ContainerPersistence/ConfigurationLoader.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/ConfigurationLoader.swift):

```swift
import ContainerPersistence

let systemConfig = try await ConfigurationLoader.load()

```

Both approaches parse the TOML hierarchy and instantiate the configuration hierarchy with appropriate fallback values.

### Inspecting Loaded Defaults

Once loaded, inspect specific container system properties to determine runtime behavior:

```swift
func printDefaults() async throws {
    let cfg = try await Application.loadContainerSystemConfig()

    print("Builder CPUs:   \(cfg.build.cpus)")
    print("Builder RAM:    \(cfg.build.memory)")
    print("Container CPUs: \(cfg.container.cpus)")
    print("Container RAM:  \(cfg.container.memory)")
    print("Default DNS:    \(cfg.dns.domain ?? "none")")
    print("Kernel URL:     \(cfg.kernel.url)")
}

```

## Customizing Default Configurations

Override container system properties by creating a custom [`config.toml`](https://github.com/apple/container/blob/main/config.toml) file in the appropriate configuration directory.

### Creating a Custom config.toml

Place your overrides at `~/.config/container/config.toml` or specify an alternative path using the `--config <path>` CLI flag:

```toml
[container]
cpus = 2
memory = "2g"

[registry]
domain = "myregistry.example.com"

```

With this configuration, any `container run` command that omits `--cpus` or `--memory` inherits the specified values (2 CPUs and 2GB RAM). Image references without explicit registries automatically resolve to `myregistry.example.com` instead of the standard `docker.io`.

### Configuration Precedence

The loading mechanism respects the following priority order:

1. User-specified configuration file (via `--config`)
2. User directory config (`~/.config/container/config.toml`)
3. System-wide configuration
4. Bundled default settings
5. Hard-coded struct defaults

This layering ensures that development environments can override production defaults while maintaining safe fallbacks for undefined properties.

## Key Configuration Sections

The `ContainerSystemConfig` struct organizes container system properties into logical domains:

### Build Configuration

Controls the builder VM characteristics used during image compilation:

```swift
let defaultImage = cfg.build.image      // Builder shim image URL
let rosettaEnabled = cfg.build.rosetta  // Apple Silicon emulation

```

Defaults include Rosetta support for non-native images, 2 CPUs, 2048MB memory, and the official builder shim from `ghcr.io/apple/container-builder-shim`.

### Container Resource Limits

Defines default compute allocations when running containers:

- **cpus**: `4` (overridden by `--cpus` flag)
- **memory**: `1g` (overridden by `--memory` flag)

### Kernel and VM Initialization

Specifies the Kata Containers kernel binary path (`opt/kata/share/kata-containers/vmlinux-6.18.15-186`) and download URL, along with the `vminit` boot image (`ghcr.io/apple/containerization/vminit`).

### Network and DNS

Configure default subnets and domain suffixes for container hostnames. The DNS domain property defaults to `nil` unless explicitly configured.

### Registry Settings

The `registry.domain` property determines where unqualified image names resolve, defaulting to `docker.io` for standard Docker Hub compatibility.

## Summary

- **Container system properties** are managed through [`config.toml`](https://github.com/apple/container/blob/main/config.toml) files decoded into `ContainerSystemConfig` structs
- **Configuration loading** occurs via `Application.loadContainerSystemConfig()` or `ConfigurationLoader.load()` in `Sources/ContainerPersistence/`
- **Default values** are hard-coded in Swift structs (e.g., `BuildConfig.defaultCPUs`, `ContainerConfig.defaultMemory`) and serve as fallbacks
- **Precedence ordering** allows user configs to override system settings while maintaining safe defaults
- **Key sections** include build parameters, container resources, kernel paths, network settings, and registry domains

## Frequently Asked Questions

### Where does apple/container look for config.toml files?

The framework searches multiple locations in descending priority: first checking paths specified with `--config`, then user configuration directories (`~/.config/container/config.toml`), followed by system-wide locations, and finally bundled defaults. Any missing values fall back to the hard-coded defaults defined in [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift).

### How do I override default CPU and memory limits for new containers?

Create a [`config.toml`](https://github.com/apple/container/blob/main/config.toml) file containing a `[container]` section with `cpus` and `memory` keys. These values apply when running `container run` or `container create` without explicit `--cpus` or `--memory` flags. For example, setting `cpus = 2` and `memory = "2g"` allocates 2 CPU cores and 2 gigabytes of RAM by default.

### Can I change the default container registry from Docker Hub?

Yes. Set the `domain` property under the `[registry]` section in your [`config.toml`](https://github.com/apple/container/blob/main/config.toml) to your private registry URL. Once configured, image references without explicit registry prefixes (such as `myimage:latest` instead of `docker.io/myimage:latest`) automatically resolve to your specified domain.

### What happens if a configuration value is missing from my TOML file?

The decoder automatically falls back to the default values defined in the struct initializers within [`ContainerSystemConfig.swift`](https://github.com/apple/container/blob/main/ContainerSystemConfig.swift). This design ensures that partial configuration files remain valid—you only need to specify values that differ from the built-in defaults, keeping your configuration files concise and maintainable.