Fundamental Operations Provided by apple/container: A Complete Guide to Swift Container Management
TLDR: apple/container implements 14 core container primitives—Create, Start, Run, Stop, Delete, Inspect, List, Exec, Logs, Kill, Prune, Stats, Copy, and Export—as OCI‑compatible Swift APIs and command‑line tools, each defined as individual structs conforming to AsyncLoggableCommand in the Sources/ContainerCommands/Container/ directory.
The apple/container repository provides a Docker‑like container runtime built entirely in Swift, designed specifically for macOS Apple Silicon virtualization. Understanding the fundamental operations it exposes is essential for developers integrating container functionality into macOS applications or interacting with the CLI.
Complete List of Fundamental Operations
The project exposes its functionality through discrete command structs located in Sources/ContainerCommands/Container/. Each operation represents a specific container management primitive.
Lifecycle Management
These operations handle the birth‑to‑death cycle of a container:
- Create (
ContainerCreate.swift): Builds a container object from an image and configuration without starting it. - Start (
ContainerStart.swift): Launches a previously created container. - Run (
ContainerRun.swift): Combines create and start into a single atomic operation, equivalent todocker run. - Stop (
ContainerStop.swift): Gracefully terminates a running container with an optional timeout parameter. - Delete (
ContainerDelete.swift): Removes a container from the system, with force‑removal support for running containers.
Monitoring and Inspection
These operations provide visibility into container state and resource usage:
- Inspect (
ContainerInspect.swift): Retrieves low‑level metadata including PID, state, mounts, and network configuration. - List (
ContainerList.swift): Enumerates containers with filtering capabilities by status, name, or label. - Stats (
ContainerStats.swift): Queries live resource consumption including CPU, memory, and I/O metrics. - Logs (
ContainerLogs.swift): Streams or fetches stdout/stderr output from a container.
Runtime Interaction
These operations manipulate running containers:
- Exec (
ContainerExec.swift): Executes arbitrary commands inside a running container and returns output. - Kill (
ContainerKill.swift): Sends signals (defaulting toSIGKILL) to the container’s init process. - Copy (
ContainerCopy.swift): Transfers files and folders between the host filesystem and container. - Export (
ContainerExport.swift): Archives a container’s filesystem as a tar file.
Maintenance and Cleanup
- Prune (
ContainerPrune.swift): Bulk‑removes stopped containers with optional filtering criteria.
Architecture of Container Operations
The fundamental operations follow a layered architecture that separates the CLI interface from the underlying runtime.
ContainerCLI (Sources/CLI/ContainerCLI.swift) parses user arguments and acts as the entry point. It forwards commands to ContainerClient (Sources/Services/ContainerAPIService/Client/ContainerClient.swift), which handles client‑side RPC communication. The client interacts with ContainersService (Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift) on the daemon side, which ultimately delegates to RuntimeService (Sources/Services/RuntimeLinux/Server/RuntimeService.swift) for virtual‑machine‑based container execution.
This design ensures that the same fundamental operations are available both via command line and as programmable Swift APIs.
Working with Fundamental Operations in Swift
Each operation is implemented as an AsyncLoggableCommand conforming struct that you can instantiate and execute programmatically.
Running a Container
The ContainerRun operation combines creation and startup:
import ContainerCommands
import ContainerResource
let run = ContainerRun(
image: "docker.io/library/alpine:latest",
command: ["/bin/sh", "-c", "echo hello && sleep 5"]
)
try await run.execute()
This corresponds to ContainerRun in Sources/ContainerCommands/Container/ContainerRun.swift.
Listing Containers
Filter containers by state using ContainerList:
import ContainerCommands
let list = ContainerList(filters: ContainerListFilters(state: .running))
let result = try await list.execute()
print(result) // JSON array of ContainerStatus structs
Implementation resides in Sources/ContainerCommands/Container/ContainerList.swift.
Fetching Container Logs
Retrieve stdout and stderr without streaming:
import ContainerCommands
let logs = ContainerLogs(containerID: "my‑container", follow: false)
let output = try await logs.execute()
print(output) // Combined stdout and stderr
Defined in Sources/ContainerCommands/Container/ContainerLogs.swift.
Executing Commands Inside Running Containers
Use ContainerExec to run arbitrary binaries inside active containers:
import ContainerCommands
let exec = ContainerExec(
containerID: "my‑container",
command: ["ls", "-la", "/"]
)
let result = try await exec.execute()
print(result) // Command output string
See Sources/ContainerCommands/Container/ContainerExec.swift for implementation details.
Pruning Stopped Containers
Bulk cleanup uses the ContainerPrune operation:
import ContainerCommands
let prune = ContainerPrune()
let summary = try await prune.execute()
print("Pruned \(summary.removedCount) containers")
This operation is implemented in Sources/ContainerCommands/Container/ContainerPrune.swift.
Summary
The apple/container project provides a comprehensive set of OCI‑compatible fundamental operations:
- Lifecycle control through Create, Start, Run, Stop, and Delete
- Observability via Inspect, List, Stats, and Logs
- Runtime management with Exec, Kill, Copy, and Export
- Maintenance using Prune for bulk cleanup
These operations are implemented as discrete Swift structs in Sources/ContainerCommands/Container/, orchestrated through ContainerCLI and ContainerClient, and executed via the daemon‑side ContainersService and RuntimeService.
Frequently Asked Questions
What is the difference between Run and Create+Start in apple/container?
Run (ContainerRun) is a convenience wrapper that executes both creation and startup atomically, equivalent to docker run. Create (ContainerCreate) only instantiates the container configuration and filesystem overlay without launching the process, allowing you to modify settings before calling Start (ContainerStart). Use separate calls when you need to inspect or adjust the container configuration between creation and execution.
How does apple/container handle container logs?
The Logs operation (ContainerLogs in Sources/ContainerCommands/Container/ContainerLogs.swift) retrieves stdout and stderr streams from the container. It supports both one‑time fetching and following mode for real‑time streaming. The operation interfaces with the daemon’s logging infrastructure through the ContainersService layer.
Can I use these fundamental operations without the command-line interface?
Yes. All operations are exposed as Swift structs conforming to AsyncLoggableCommand in the ContainerCommands module. You can import the package into your Swift application and call execute() on any operation directly, bypassing the ContainerCLI parser entirely. The ContainerClient class provides the underlying RPC mechanism for programmatic access.
How does the Copy operation manage file permissions between host and container?
Copy (ContainerCopy in Sources/ContainerCommands/Container/ContainerCopy.swift) handles bidirectional file transfers between the host filesystem and container root filesystem. It preserves Unix permissions and ownership metadata during transmission. The operation uses the runtime’s virtualization layer to ensure secure file system isolation while allowing data exchange between the host and guest environments.
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 →