How to Create a Container Without Starting It Using `container create`

To create a container without starting it, use the container create command followed by your image reference, which initializes the container filesystem and configuration while keeping the process in a Created state until you explicitly invoke container start.

The apple/container framework provides a distinct lifecycle phase for container initialization that separates resource allocation from process execution. Unlike container run, which immediately spawns a process, the container create command allows you to create a container without starting it, enabling pre-staging, configuration validation, and resource preparation without runtime overhead.

How container create Works in the Apple Container Framework

According to the source code in Sources/CLI/ContainerCreateCommand.swift, the container create subcommand parses user arguments through Swift ArgumentParser, resolves the image reference, and constructs a ContainerSpec object. This specification captures all configuration parameters—including environment variables, resource limits, and network settings—before persisting the container to the local store.

The runtime implementation, found in Sources/ContainerRuntime/Runtime.swift and Sources/ContainerRuntime/ContainerSpec.swift, materializes the ContainerSpec into a persisted container object. During this phase, the system allocates the filesystem and metadata storage but explicitly avoids calling exec or spawning any init process. This leaves the container in a Created state, as documented in docs/command-reference.md.

Key Differences Between container create and container run

While both commands accept identical flags for process, resource, and network configuration, they diverge at the execution boundary.

Resource consumption is the primary distinction: container create does not consume CPU or memory beyond the minimal footprint required to persist the container state, whereas container run immediately allocates runtime resources and begins process execution.

Lifecycle flexibility represents another critical difference. After creation, you can inspect the container with container inspect, modify its configuration (such as adding mounts), or stage multiple containers for batch initialization. The container remains dormant until explicitly activated via container start, allowing for surgical control over initialization timing.

Supported Flags and Configuration Options

The container create command mirrors the flag interface of container run, supporting all standard configuration options. Validated parameters include:

  • --name to assign a unique identifier
  • --env or -e for environment variables
  • --cpus and --memory for resource constraints
  • --network for network attachment
  • --init to enable an init process for zombie reaping
  • --init-image to specify a custom init image
  • --cap-add and --cap-drop for Linux capability management

Error validation occurs before persistence, as verified in Tests/CLITests/Subcommands/Containers/TestCLICreate.swift. Invalid configurations—such as exceeding maximum published ports or referencing unknown init images—trigger a CLIError and abort the creation process without leaving partial state.

Practical Examples for Creating Containers Without Starting

These runnable examples demonstrate common patterns for staging containers:


# Basic creation with explicit naming

container create --name my-container ubuntu:latest

# Creation with environment variables and resource constraints

container create \
  --name web-svc \
  -e NODE_ENV=production \
  --cpus 2 \
  --memory 1G \
  nginx:latest

# Using an init process for proper signal handling

container create --init --name app-with-init alpine:latest

# Specifying a custom init image for VM-level boot customization

container create --init-image my-custom-init:latest --name custom-init-test ubuntu:latest

# Starting the container when ready

container start my-container

Summary

  • Use container create instead of container run to instantiate a container without spawning processes.
  • The command persists a ContainerSpec defined in Sources/ContainerRuntime/ContainerSpec.swift to the local store, leaving the container in a Created state.
  • No CPU or memory runtime overhead occurs until container start is invoked.
  • All configuration flags supported by container run are available for pre-staging environment, resource, and network settings.
  • Validation errors trigger CLIError exceptions before any persistence occurs, ensuring atomic creation semantics.

Frequently Asked Questions

Can I modify a container after creating it but before starting it?

Yes. Because container create persists the container configuration without spawning a process, you can use container inspect to review the current configuration and modify parameters such as mounts or network attachments before invoking container start. This allows for iterative configuration refinement without runtime side effects.

Does container create consume significant system resources?

No. According to the implementation in Sources/ContainerRuntime/Runtime.swift, the creation process only allocates storage for the filesystem and metadata. The container does not consume CPU cycles or memory beyond its persisted state representation, making it suitable for pre-staging large numbers of containers without runtime overhead.

What happens if I provide an invalid image reference to container create?

The command validates the image reference during the resolution phase in Sources/CLI/ContainerCreateCommand.swift. If the image cannot be found or the reference is malformed, the CLI returns a CLIError and aborts immediately without creating partial container state, as verified by the test suite in Tests/CLITests/Subcommands/Containers/TestCLICreate.swift.

How do I check if a container was created successfully without starting it?

Use the container inspect command followed by the container name or ID. A successfully created container will display a status of Created in the output, along with the full ContainerSpec configuration including image reference, environment variables, and resource limits defined during the container create invocation.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →