26 Commits

Author SHA1 Message Date
Raj b2994ac369 Add container machine for managing persistent Linux VMs (#1662)
## Type of Change
- [ ] Bug fix
- [x] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
`container` runs each workload in an ephemeral VM, so there's no
built-in way to keep a persistent Linux environment you can log into and
work in. `container machine` adds one.

A container machine is a lightweight, persistent, and integrated Linux
environments that feel like an extension of your Mac, created from
standard OCI images with a familiar UX. The login user matches your host
account with passwordless `sudo`, your home directory is mounted inside
the VM, and each machine keeps its filesystem and runs the image's own
init system (such as`systemd` or `openrc`).

```bash
container machine create alpine:3.22 --name my-machine
container machine run -n my-machine # interactive shell
container machine set -n my-machine cpus=4 memory=8G
```

Subcommands: `create`, `run`, `list` (`ls`), `inspect`, `set`,
`set-default`, `logs`, `stop`, `delete` (`rm`); `m` aliases `machine`.
Docs added to `docs/command-reference.md` (Machine Management) and
`docs/how-to.md` ("Use container machines").

## Testing
- [x] Tested locally
- [x] Added/updated tests
- [x] Added/updated docs

Signed-off-by: Raj Aryan Singh <rajaryan_singh@apple.com>
Co-authored-by: Jaewon Hur <jaewon_hur@apple.com>
Co-authored-by: John Logan <john_logan@apple.com>
Co-authored-by: Michael Crosby <michael_crosby@apple.com>
Co-authored-by: Eric Ernst <eric_ernst@apple.com>
Co-authored-by: Danny Canter <danny_canter@apple.com>
2026-06-08 11:38:49 -07:00
J Logan ca3a4d6670 Use FilePath for app, install, and log roots. (#1558)
- Closes #1557.
- Replaces `executableURL` utility function for getting app executable
path with `executablePath`.
- Adds `FilePath.resolvingSymlinks()` extension.
- Also converts for FilePath for types in `ContainerVersion` target.
2026-05-26 13:58:55 -07:00
Noah Thornton 9be1020679 Move to TOML configuration for plugin configurations (#1422)
This change migrates plugin config format away from using JSON to use
TOML.
- Addresses the plugin portion of discussion #1336

## Type of Change
- [ ] Bug fix
- [X] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
Context within https://github.com/apple/container/discussions/1336

> We're looking to improve the user experience and overall functionality
of setting defaults for container to better enable future use cases.
> 
> Today container uses macOS's
[UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults)
to configure settings needed at runtime. As mentioned in
https://github.com/apple/container/issues/608, UserDefaults may be
idiomatic for macOS, but they apply globally to all sessions and do not
handle representing complex, hierarchical data well. Additionally, we
currently have two ways of setting these defaults, either directly with
macOS's defaults command or through container system property.
> 
> https://github.com/apple/container/issues/608 proposes moving to use
environment variables in place of UserDefaults. However, we do not
believe this is sufficient. Environment variables are not in a
consistent location, are not sourced from data, and also do not handle
representing complex, hierarchical data well.

As part of this migration to TOML for user settings we want to also move
plugin settings to use TOML so that we can have a singular file format
for `container` configurations.


## Testing
- [X] Tested locally
- [X] Added/updated tests
- [ ] Added/updated docs
2026-04-17 10:56:46 -07:00
jwhur 5fb62ab18c Add plugin resources (#1356)
This PR adds a feature passing resource directory for the plugins.

When a `resources` directory is detected under the plugin's
`installURL`, the path to `resources` directory is passed as an argument
(i.e., `--resources <path>`) to the plugin `start`.

Resource files are distributed and installed together with the
`container` binary.

## Type of Change
- [ ] Bug fix
- [X] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
Plugin developers can convey resource files (e.g., shell scripts) under
the `resources` directory.

## Testing
- [X] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
2026-03-27 15:15:43 -07:00
jwhur 24f6b747f1 Reap auto remove containers if there are running on system start (#1290)
This PR reaps already running containers with auto remove flag on
container system start.

Container API server shutdown ideally should stop every running
container, and reap the containers with auto remove flag. However, crash
or unexpected exit of API server leaves the containers running. In such
case, next system start should stop running containers (i.e., launchd
services) and reap the containers with auto remove flag.

## Type of Change
- [X] Bug fix
- [ ] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
Preserve the system to be in a consistent state after unexpected
failure.

## Testing
- [X] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs

---------

Co-authored-by: Raj <realrajaryan@gmail.com>
2026-03-13 09:14:45 -07:00
J Logan d29947121f CI observability enhancements. (#1193)
- Adds a a `--log-root` option to `swift system start`, propagating the
value as `CONTAINER_LOG_ROOT` to services for logging to files instead
of the OS log facility. This is not a "production" capability as it
neither merges nor rotates logs.
- Currently we don't collect logs on CI builds, and we don't have
permission to run the `log` command there. The PR adds `--log-root` to
the CI test phase, archives the results, and uploads the archive as an
artifact.
- Use FilePath from swift-system for the log root. Foundation URL is a
bit of a footgun for filesystem paths, so unless we identify a
showstopper, we should incrementally transition to this type everywhere
except where we really need network URLs.
- Output the hostname of the CI runner at the start of the test phase so
we can identify runner-specific issues where they exist.
- Fix formatting for log messages with multiple metadata items, and fix
unstructured messages on instances that weren't found using `grep -r
'log\.' Sources`.
- Adds command reference documentation for `--log-root`.
2026-02-19 17:47:41 -08:00
J Logan 3ad0914fd2 Fix CI integration test coldstart issues. (#1230)
- Closes #1206.
- Closes #1185.
- Closes #507.
- Addresses existing log messages for #642.
- Nondeterministic CI errors are resulting from very slow launch times
for the first runtime helper, which causes ContainersService to be
locked for longer than our 20 sec timeout. Bumping the timeout to 60
seconds addresses this case for now.
- Since many log messages needed to be changed to troubleshoot the
issue, updated all log messages to use structured logging, and
implemented consistent entry/exit logging for all service operations.
- Added logging for ContainerService lock acquisition to help with
finding root cause for the slow service startup.
- Plumbed the `--debug` flag on both `container system start` and
`container system logs` so that the flag is actually useful.
- Updated the `install-init.sh` script so that can install in a custom
app root directory.
2026-02-19 09:58:09 -08:00
jwhur d762fe55a2 Launch a service with waitForDebugger if specified (#1101)
This PR enables launching a service with `waitForDebugger` flag if the
service label matches a given env variable `CONTAINER_DEBUG`.
2026-01-28 18:22:33 -08:00
Kathryn Baldauf 9032d73d07 Change behavior of the default arguments in the plugin config (#1063)
## Type of Change
- [x] New feature  
- [x] Breaking change

## Motivation and Context
This PR changes the behavior of the `defaultArguments` field in the
service plugin config. Previously, `defaultArguments` was functioning as
a way to indicate how to start a plugin in the event that the plugin is
loaded at boot (such as for the `container-core-images plugin`).
However, we now follow a convention where all plugins have a "start"
command that is used when launching the plugin, so this
`defaultArguments` field wasn't really providing much. Instead, there
are use cases where we may want to set default values to pass to a
plugin. This PR repurposes the `defaultArguments` field for those use
cases.

As an example use case, there are scenarios where someone may want to
use the AllocationOnlyVmnetNetwork even when running on macOS 26+. This
PR adds the ability to pass in a command line option to the vmnet
network plugin to specify that request. Combined with the
`defaultArguments` plugin config change, a user may choose to set that
field to ["--variant", "allocationOnly"] in the
`container-network-vmnet-config.json` to use AllocationOnlyVmnetNetwork
by default for all networks.

## Testing
- [x] Tested locally
2026-01-19 19:22:55 -08:00
Kathryn Baldauf d6f052d206 Update license header on all files to include the current year (#1024)
## Motivation and Context
Now that we're in 2026, we need to update the license headers on all the
files. Unfortunately, Hawkeye doesn't have an attribute for the current
year to help us avoid this in the future. Instead, I had to work around
this by doing the following:

1. Update licenserc.toml with:
     ```
      [properties]
       ... (other properties)
       currentYear = "2026"
     ```
 
2. Update scripts/license-header.txt with
    ```
Copyright ©{{ " " }}{%- set created = attrs.git_file_created_year or
attrs.disk_file_created_year -%}{%- set modified = props["currentYear"]
-%}{%- if created != modified -%} {{created}}-{{modified}}{%- else
-%}{{created}}{%- endif -%}{{ " " }}{{ props["copyrightOwner"] }}.
    ```

Then I removed these two changes before committing. After this PR is
merged, all files will have recently had git updates, so the existing
code for setting the modified year should work as intended.

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2026-01-05 13:09:34 -08:00
Dmitry Kovba 38960553cb Lowercase error messages (#945)
## Type of Change
- [x] Bug fix
- [ ] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
For consistency, all error messages are lowercased.

## Testing
- [ ] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs

---------

Co-authored-by: J Logan <sgtbakerrahulnet@yahoo.com>
2025-12-09 12:32:28 -08:00
J Logan 936c916916 Actually resolve symlink when loading bundle Info.plist. (#864)
- #859 added the traversal necessary to load the app bundle but forgot
to resolve symlinks. This fix adds the resolution, making it possible to
get default system properties from an app bundle Info.plist even if the
user invokes a command from, for example, `/usr/local/bin/container`
which is a symlink to the actual install path of the bundle.
- Also fixes bugs where an incorrect executable path was supplied in
some calls.
- Breaking change: `CommandLine.executablePathUrl` extension moved from
ContainerPlugin to ContainerVersion.
2025-11-10 17:00:18 -03:00
Dmitry Kovba 4944fe1641 Use a consistent capitalization in log and error messages (#806)
Updates the capitalization in log and error messages to be consistent.
2025-10-24 19:18:32 -07:00
J Logan bc70b39182 Fix broken proxy configuration for default kernel fetch. (#747)
- Closes #466.

## Type of Change
- [x] Bug fix
- [ ] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
Proxy logic worked well enough for CI but broken in general.

## Testing
- [x] Tested locally
- [x] Added/updated tests
- [ ] Added/updated docs
2025-10-10 10:17:42 -07:00
Kathryn Baldauf 23b058c53c Remove StandardErrorPath and StandardOutPath from launchd plists (#742)
## Type of Change
- [x] Bug fix

## Motivation and Context
We setup logging for the services in `container` using OSLog. See
[here](https://github.com/apple/container/blob/73709232d2705b7008b7380fe90a373059b6074a/Sources/Helpers/APIServer/APIServer.swift#L31).
This makes it unnecessary to redirect stderr and stdio for these
services. Additionally, there are some cases where failure to open or
write to the path given for StandardErrorPath or StandardOutPath in a
service's plist could result in a failure to start a service through
`launchctl`.

Related to https://github.com/apple/container/discussions/713

## Testing
- [x] Tested locally

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2025-10-08 16:08:08 -07:00
J Logan bfc5ca9222 Removes "all rights reserved" from license header. (#711)
Closes #63.
2025-10-03 13:28:16 -07:00
Dmitry Kovba 48230f3804 Update license headers in C files (#693)
## Type of Change
- [x] Bug fix
- [ ] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
There was a duplicated and outdated license header in some files.

## Testing
- [x] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
2025-10-02 09:42:24 -07:00
J Logan 879dff8fcf Allow traversing symlink when checking for builtin plugins. (#528)
- This helps with brew cask packaging, can postflight link
libexec/container/plugins to the appropriate cask location, and the
plugin discovery will traverse the link.
2025-08-20 23:52:24 -07:00
J Logan 6242706c66 Fixes for install root and plugin detection. (#467)
- Sets up API server as source of truth for installation root, similarly
to what was done for the data root. `system start` establishes the
install root, setting the environment variable `CONTAINER_INSTALL_ROOT`
when launching the API server.
- The API server propagates the environment variable when launching
helpers, and returns the install root to the CLI via the health check
XPC.
- Includes several fixes for detecting plugins that use app bundle
layout.
2025-08-08 21:44:26 -07:00
J Logan 88223d8add Select alternate data path with container system start --app-root path. (#419)
Closes #418.
2025-08-06 14:49:09 -07:00
J Logan 2e1bee1bda Fix subcommand groups in top level help. (#351)
- Closes #349.
2025-07-17 22:10:03 -07:00
J Logan 1707e1b530 Use {install-root}/libexec/container-plugins for plugins. (#341)
- Use a directory that's separate from user data, as user-installed
plugins have a distinct lifecycle.
- Closes #340.
2025-07-15 18:18:38 -07:00
Josh Soref 4a4ad40d74 Spelling (#207)
This PR corrects misspellings identified by the [check-spelling
action](https://github.com/marketplace/actions/check-spelling)

The misspellings have been reported at
https://github.com/jsoref/container/actions/runs/15662939575/attempts/1
The action reports that the changes in this PR would make it happy:
https://github.com/jsoref/container/actions/runs/15662939742/attempts/1#summary-44123289718

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-06-16 10:49:03 -07:00
Danny Canter 4d6f7037f3 Plugins: Remove unused devnull var (#214)
We actually use the output (both stderr and stdout) of the command.
2025-06-16 08:11:25 -07:00
Eliseo Martelli 84798601cd Throw errors in ServiceManager (#188) 2025-06-13 17:07:55 -07:00
Kathryn Baldauf 8e9670c8f8 Initial commit
Co-authored-by: Aditya Ramani <a_ramani@apple.com>
Co-authored-by: Agam Dua <agam_dua@apple.com>
Co-authored-by: Danny Canter <danny_canter@apple.com>
Co-authored-by: Dmitry Kovba <dkovba@apple.com>
Co-authored-by: Eric Ernst <eric_ernst@apple.com>
Co-authored-by: Evan Hazlett <ehazlett@apple.com>
Co-authored-by: Gilbert Song <gilbertsong@apple.com>
Co-authored-by: Hugh Bussell <hbussell@apple.com>
Co-authored-by: John Logan <john_logan@apple.com>
Co-authored-by: Kathryn Baldauf <k_baldauf@apple.com>
Co-authored-by: Madhu Venugopal <mvenugopal@apple.com>
Co-authored-by: Michael Crosby <michael_crosby@apple.com>
Co-authored-by: Sidhartha Mani <sidhartha_mani@apple.com>
Co-authored-by: Tanweer Noor <tnoor@apple.com>
Co-authored-by: Ximena Perez Diaz <xperez528@gmail.com>
Co-authored-by: Yibo Zhuang <yzhuang@apple.com>
2025-06-05 15:51:55 -07:00