How to Create a Container Without Starting It Using `container create`
Use container create with your image reference and configuration flags to instantiate a container in a stopped state, allowing you to start it later with container start when you are ready to execute the process.
The container create command in the apple/container repository provides a lightweight way to instantiate a container from an image without immediately launching its init process. This approach allows you to configure, inspect, and prepare container environments before consuming runtime resources, making it ideal for batch staging and pre-deployment validation.
How container create Works Under the Hood
When you execute container create, the system constructs a container object—including its filesystem, metadata, and configuration—and persists it in the local store. The container enters a Created state without spawning any processes, meaning it consumes no CPU or memory beyond its persisted state until explicitly started.
CLI Implementation and Validation
The command is implemented in Sources/CLI/ContainerCreateCommand.swift, where the Swift ArgumentParser setup registers the sub-command and handles argument parsing. This module resolves the image reference, validates input parameters, and constructs the container specification.
Validation occurs before creation, with errors such as exceeding maximum published ports or specifying unknown init images causing immediate aborts with descriptive CLIError messages. The unit tests in Tests/CLITests/Subcommands/Containers/TestCLICreate.swift verify these edge cases, including MAC address handling and port-publish limits.
Container Specification Construction
During execution, the CLI builds a ContainerSpec object (defined in Sources/ContainerRuntime/ContainerSpec.swift) that captures the image reference, environment variables, resource limits, and metadata. This specification serves as the blueprint for the container's eventual execution environment.
Runtime Materialization Without Execution
The core runtime logic (located in the runtime implementation files) materializes the ContainerSpec into a persisted container without invoking the exec system call. Unlike container run, which immediately spawns the init process, container create stops after resource allocation and filesystem preparation, leaving the container dormant until you explicitly call container start.
Practical Examples: Creating Containers Without Starting
Here are practical patterns for using container create to prepare containers for later execution:
# 1️⃣ Basic creation – container remains stopped after this command
container create --name my-container ubuntu:latest
# 2️⃣ Add environment variables and resource limits
container create \
--name web-svc \
-e NODE_ENV=production \
--cpus 2 \
--memory 1G \
nginx:latest
# 3️⃣ Use an init process (reaps zombies & forwards signals)
container create --init --name app-with-init alpine:latest
# 4️⃣ Create with a custom init image for VM-level boot customization
container create --init-image my-custom-init:latest --name custom-init-test ubuntu:latest
# 5️⃣ Start the container when you are ready to execute
container start my-container
Supported Configuration Flags
container create accepts essentially the same set of process, resource, and management flags as container run, allowing you to fully configure the container before starting it. According to the command reference documentation, supported options include:
- Process and environment:
--name,--env,--env-file - Resource constraints:
--cpus,--memory,--pids-limit - Networking:
--network,--publish,--hostname - Init process control:
--init,--init-image - Capabilities:
--cap-add,--cap-drop - Storage:
--volume,--mount
This parity means you can define the complete execution environment during creation, then launch it later with all configurations intact.
Use Cases for Creating Without Starting
Creating containers without immediate execution enables several operational workflows:
- Pre-staging: Prepare containers during low-traffic periods for rapid batch start-up during peak times
- Configuration inspection: Run
container inspectto verify the container configuration before committing runtime resources - Pre-start modification: Add mounts, adjust network settings, or review security contexts while the container remains dormant
- Lightweight health checks: Validate image integrity and configuration parsing without incurring process execution overhead
Summary
- Use
container createto instantiate a container from an image without launching processes, leaving it in a Created state - Configuration parity: The command accepts the same flags as
container run, including environment variables, resource limits, and networking options - Zero runtime overhead: No CPU or memory consumption occurs until
container startis invoked - Implementation locations: Core logic resides in
Sources/CLI/ContainerCreateCommand.swiftandSources/ContainerRuntime/ContainerSpec.swift - Validation: Input validation prevents creation errors before persistence, with test coverage in
Tests/CLITests/Subcommands/Containers/TestCLICreate.swift
Frequently Asked Questions
What is the difference between container create and container run?
container create builds and persists the container configuration without executing the init process, leaving the container in a stopped state. container run combines creation and execution, immediately spawning the container's process after instantiation. Use container create when you need to prepare or inspect the container before execution, and container run when you want immediate execution.
Can I modify a container after creating it but before starting it?
Yes, after using container create you can inspect the container with container inspect to verify its configuration, and in some implementations modify attributes like mounts or network settings. The container remains in a mutable state until you invoke container start, at which point the runtime finalizes the execution environment and launches the init process.
What flags are supported by container create?
The command supports essentially the same flags as container run, including --name, --env, --cpus, --memory, --network, --init, --init-image, --cap-add, and --cap-drop. This allows you to fully configure the container's environment, resource constraints, and security context during creation, ensuring the container is ready to execute exactly as specified when you later call container start.
How do I start a container that I created with container create?
Execute container start <container-name> to transition the container from the Created state to Running. This command invokes the runtime to spawn the init process using the previously persisted configuration, at which point the container begins consuming CPU and memory resources according to the limits specified during creation.
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 →