How to Manage Container Builder Instances Using Start, Status, and Stop Commands
Use the container builder start, container builder status, and container builder stop subcommands to control the BuildKit-based builder container lifecycle, with idempotent operations that handle resource constraints and DNS configuration automatically.
The apple/container repository provides a lightweight Container Builder that wraps BuildKit in a managed container environment. Learning how to manage container builder instances through the CLI ensures you can programmatically control build resources, verify service availability, and gracefully shut down the builder when workloads complete.
Understanding the Container Builder Architecture
The Container Builder is identified by a fixed container ID defined in Sources/ContainerResource/Common/ResourceLabels.swift. All lifecycle commands target the constant builderContainerId (value: "buildkit"), ensuring consistent state management across start, status, and stop operations.
The three primary subcommands are implemented in separate Swift files under Sources/ContainerCommands/Builder/:
- BuilderStart.swift – Handles image resolution, container creation, and BuildKit bootstrap
- BuilderStatus.swift – Queries runtime state and reports human-readable status
- BuilderStop.swift – Executes graceful shutdown via the container runtime
Starting the Builder with container builder start
The container builder start command implements idempotent container provisioning in Sources/ContainerCommands/Builder/BuilderStart.swift. When executed, the start method first fetches the builder image referenced by containerSystemConfig.build.image, then checks for existing containers via client.get(id: "buildkit").
Configuration change detection occurs between lines 71–78: if a running container exists but differs in image, CPU, memory, environment, or DNS settings from the requested configuration, the command automatically stops and deletes the old container before recreating it. If the container is stopped but matches the requested configuration, the command simply restarts the BuildKit process inside the existing container (lines 80–84).
Resource allocation uses the Parser.resources helper to convert CLI flags into a Resources struct:
container builder start \
--cpus 4 \
--memory 8G \
--dns-nameserver 8.8.8.8 \
--dns-search example.com
The command attaches the builder to the default vmnet network and mounts /run as tmpfs alongside the export directory at /var/lib/container-builder-shim/exports. Environment variables BUILDKIT_COLORS and NO_COLOR are automatically forwarded from the host process.
Checking Builder State with container builder status
Query the builder's runtime state using container builder status, implemented in Sources/ContainerCommands/Builder/BuilderStatus.swift. This command calls ContainerClient.get(id: "buildkit") and inspects the container.status field to determine whether the builder is running, stopped, or absent.
The output provides clear, actionable feedback:
# Standard output
container builder status
# → "builder is running" or "builder is not running"
# Script-friendly quiet mode
container builder status --quiet && echo "Running" || echo "Stopped"
When the --quiet flag is supplied, the command suppresses output when the builder is not running, enabling shell scripts to rely solely on exit codes for state detection.
Stopping the Builder with container builder stop
Gracefully terminate the builder using container builder stop, defined in Sources/ContainerCommands/Builder/BuilderStop.swift. This invokes client.stop(id: "buildkit") to send a termination signal to the container's init process, allowing BuildKit to complete active builds before shutting down.
The operation is safe to run repeatedly; if the builder is already stopped, the command returns a harmless warning rather than failing. For complete removal after stopping, use the delete command with force:
# Graceful stop
container builder stop
# Force stop and remove container
container builder delete --force
Programmatic API Usage
For custom tooling, import the ContainerAPIClient and ContainerBuild modules to manage the builder lifecycle directly:
import ContainerAPIClient
import ContainerBuild
import Logging
let client = ContainerClient()
let logger = Logger(label: "my.tool")
// Start with specific resources
try await BuilderStart.start(
cpus: 2,
memory: "4G",
log: logger,
dnsNameservers: [],
dnsDomain: nil,
dnsSearchDomains: [],
dnsOptions: [],
progressUpdate: { _ in },
containerSystemConfig: await Application.loadContainerSystemConfig()
)
// Query status
if let container = try? await client.get(id: "buildkit") {
print("Builder status: \(container.status)")
}
// Stop the builder
try await client.stop(id: "buildkit")
The Tests/IntegrationTests/Build/BuildFixture.swift file provides additional reference implementations for builderStart, builderStop, and builderDelete methods used in the test suite.
Summary
- Container identification is fixed to the
"buildkit"container ID across all commands, ensuring consistent targeting. container builder startprovisions or reuses containers, automatically recreating them when resource, DNS, or image configuration changes.container builder statusreports runtime state and supports--quietmode for script automation.container builder stopexecutes graceful shutdowns that are safe to invoke multiple times.- The architecture ensures idempotent operations, preventing duplicate container creation or error conditions on repeated commands.
Frequently Asked Questions
What happens if I run container builder start when the builder is already running?
According to the implementation in BuilderStart.swift, the command compares the existing container's configuration against the requested parameters. If the running container matches the requested CPU, memory, DNS, and image settings, the command succeeds without modification. If configuration differs, it stops and removes the existing container before creating a new one with the updated specifications.
How does the container builder status --quiet flag differ from standard output?
The --quiet flag suppresses the "builder is not running" message when the container is absent or stopped, emitting no output to stdout. This allows shell scripts to check the exit code (0 for running, non-zero for not running) without parsing text output, making it ideal for CI/CD pipelines and automation scripts.
Can I customize the builder image used when starting the container?
Yes, the builder image is determined by the build.image property in ContainerSystemConfig.swift. While the CLI uses the system configuration by default, you can modify the configuration source or use the programmatic API to pass a custom containerSystemConfig with a different image reference to BuilderStart.start().
Is it safe to stop the builder while builds are in progress?
The client.stop(id:) method sends a graceful termination signal to the container's init process. Active BuildKit operations should complete before shutdown occurs, though the exact behavior depends on the container runtime's stop signal handling. For immediate termination, the builder delete --force command stops and removes the container without waiting for graceful shutdown.
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 →