- Closes#1268.
- The types we were using weren't very usable with Swift 6 structured
concurrency.
- Implements just the subset of records that we use.
- Use notImplemented instead of formatError for unknown record types.
- Use pure actor for LocalhostDNSHandler now that we have sendable
types.
- Use DNSName as key for table lookups in LocalhostDNSHandler and
HostTableResolver.
- Utilize dot-suffixed domain names everywhere in the lookup chain.
- Huge thanks to @manojmahapatra and @katiewasnothere for their
diligent and patient review :D
This PR adds an option in `ContainerCreateOption` to override the root
filesystem of container. When `ContainerCreateOption.rootFsOverride` is
set, container uses that as the root fs instead of the one cloned from
image snapshot.
## Type of Change
- [ ] Bug fix
- [X] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
[Why is this change needed?]
## Testing
- [X] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
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>
- Closes#1252 (part of #913).
- Commands that accept `--platform` currently require it
to be passed explicitly every time. Users working
consistently with a non-native platform (e.g. `linux/amd64`
on Apple Silicon) have no way to set a default, unlike
Docker's `DOCKER_DEFAULT_PLATFORM`.
- This adds support for the `CONTAINER_DEFAULT_PLATFORM`
environment variable as a fallback when `--platform` is not
explicitly provided.
This PR fixes#1277.
`SandboxService.waiters` had a consistency issue (not exactly race).
`SandboxService.wait` XPC can be executed on arbitrary `id`, and it will
hang forever if no other handler resumes it. Without knowing this
internal, the high level entity can run into this issue, and deadlock.
This PR simplifies the mental model: **`SandboxService.waiters[id]:
ExitWaiter(continuations, exitCode)` can only be in three states: i)
non-existing, ii) existing with nil `exitCode`, and iii) existing with
concrete `exitCode`.**
**If it is non-existing, no handler has been registered to resume it
later. If existing with nil `exitCode`, It is guaranteed the registered
`continuations` will be resumed later with a concrete `exitCode`.
Finally, if already a concrete `exitCode`, a handler has been
registered, and already resumed (with that `exitCode`).**
Thus, `SandboxService.wait` should return immediately if `waiters[id]`
is non-existing or existing with a concrete `exitCode` (as no handler
will resume it later). It should only block when `waiters[id]` is
existing with nil `exitCode` as it is guaranteed to be resumed later. By
doing so, we can guarantee there is no deadlock at all.
For that this PR does followings:
1. Introduce `ExitMonitor` class to updates `continuations` and
`exitCode` all together atomically. Initially, `state` variable saved
the `exitCode`, but it cannot be tied with `continuations` as they are
protected by different primitives (i.e., lock and actor).
2. Gather `waiters` related operations into a single actor method,
guaranteeing those are performed atomically under actor
protection---i.e., we actually don't need Mutex here.
3. Ensure initialized `waiters` are released (i.e., resumed) later
(under any possible circumstances).
4. Move `process.wait` after `process.start` in `io.handleProcess` to
run `SandboxService.wait` only after the `waiters[id]` is initialized.
By doing fourth step, we can guarantee `SandboxService.wait` can meet
only one of two following `ExitMonitor` state: i) existing with nil
`exitCode`, or ii) existing with concrete `exitCode` (in case the
process exited too early). In both cases, `exitCode` is preserved and
returned.
## Type of Change
- [X] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
[Why is this change needed?]
## Testing
- [X] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
Fix container hang when starting an invalid executable (#1277).
Ensure the `SandboxService.waiters` updated atomically, preventing a slow `wait` from registering continuation after the `SandboxService` has been stopped.
Current `ProcessIO.handleProcess` has races between `process.wait()` and
`process.start()`. In `process.wait`, `SandboxService.wait` registers
and block on a continuation so that later exit of that `LinuxContainer`
can resume it.
Even if `SandboxService.wait` checks the container state, there can be a
race so that `SandboxService.startInitProcess` fails earlier with no
continuation to resume, then `SandboxService.wait` registers the
continuation, which forever hang the thread.
Closes#1225
Add a flag to signify that we'd like to run a minimal init process that
can reap zombie processes. The actual support for this is in the
Containerization library so the plumbing here is very simple.
- This reverts commit 1942a399e3.
- This approach to getting variant into the runtime helper was fine for
proof of concept work but we need a persistent runtime config file so
that the variant is available for `container start`.
- Adds plugin variant selection to bootstrap() on the Container API
service in such a way that we can revert the change soon without
compatibility issues when we work out a more permanent approach, and
requires no persistent data migration.
- Restore lexical ordering on ManagementFlags (except `--runtime`, will
take care of that next PR).
- Add a couple plugin loader tests to improve coverage.
## Type of Change
- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
As reported in [1212](https://github.com/apple/container/issues/1212),
environment variables defined in a Dockerfile (ENV) were not being
overridden when passed via -e at runtime, resulting in duplicate entries
in the container's environment.
**Root cause:** `Parser.allEnv()` simply merged image, env-file, and
user-provided environment variables without deduplication. Since
`getenv()` returns the first match, the image default took precedence
over the user override.
**Fix:** `allEnv()` now deduplicates by key, with later sources
overriding earlier ones
## Testing
- [x] Tested locally
- [x] Added/updated tests
- [ ] Added/updated docs
- Closes#1236.
- As with other resources, default to tabular output, with `--format
json` alternative.
- Also changes common workflow to collect logs even when test step times
out.
- 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`.
- 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.
## Type of Change
- [ ] Bug fix
- [x] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
Authors of CLI plugins for container will be able to reuse the container
flags defined in the CLI package, instead of having to duplicate them in
their project
## Testing
- [ ] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
Closes#1202
Today it's possible to pass a memory amount that very easily will cause
the container's VM to not be able to boot. We should protect against
this to avoid weird hangs/error messages. I could be convinced that a
limit should be in Containerization as well, but I think having one in
the daemon is a decent idea regardless.
## Type of Change
- [x] New feature
- [x] Breaking change
## Motivation and Context
We want to be able to support using multiple network plugins during
`container`'s lifetime. This additionally means needing to pick an
interface strategy to interpret a network attachment based on what
network plugin was used to create that attachment. This PR will
potentially replace https://github.com/apple/container/pull/1081.
Followups:
- doc updates to include the ability to specify plugin in the network
creation cli
## Testing
- [x] Tested locally
- [x] Added/updated tests
## Type of Change
- [ ] Bug fix
- [x] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
Closes#1046 -- Right now we're creating container bundles in
ContainersService. Move this to the SandboxService to make it easier to
support different container bundle types.
## Testing
- [x] Tested locally
- [x] Added/updated tests
- [ ] Added/updated docs
This is not intended to be used to support `--filter` or similar on the
CLIs list yet, it's solely to clean up our rather awkward use of
`ContainerClient.list()` today in the CLI. The list RPC simply returns
all of the containers we have created. Because of this, for a LOT of our
commands we filter to what we need client side, which feels like a
waste.. This change introduces a filter struct that we can provide an
array of container IDs, labels, and the status of the containers to
filter the `list()` output from.
This additionally, because it was killing (pun not intended) me and I
was already having to change this area for the `list()` additions,
changes container kill slightly to return an error if you try and kill a
container that doesn't exist.
`make test` occasionally fails with:
```
✘ Test testHostDNSReinitialize() recorded an issue at HostDNSResolverTest.swift:132:45: Expectation failed: (error →
Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory") as? (ContainerizationError → NSError)
✘ Suite HostDNSResolverTest failed after 0.119 seconds with 1 issue.
```
- Implemented the TODO at
ContainerAPIService/Client/Utility.swift:358 — warn the
user when a named volume is auto-created.
- This only triggers for named volumes (not anonymous
ones), matching Docker's behavior of informing users
about implicit resource creation.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Closes#1150.
- The problem seems to be that the selinux label attribute enforcement
doesn't play well with overlayfs.
- Solution is to set the `lsm` boot line argument. The new value
corresponds to what one would see in a Lima VM with Colima. The Kata
kernel we use doesn't provide any of those modules, so now if you run
`dmesg | grep -i lsm` in a container you will just see: `LSM:
initializing lsm=capability`
Send the hash of entire tar file in the first BuildTransfer packet to
prevent container-builder-shim from using stale cached contents.
This PR resolves#1143.
This PR relies on apple/container-builder-shim#64.
## Type of Change
- [X] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
Current container-builder-shim uses only first few bytes of tar file as
checksum, which leads to the usage of stale cached contents if the
change of build context is not included in the first bytes of tar file.
## Testing
- [X] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
---------
Co-authored-by: Ronit Sabhaya <ronitsabhaya75@gmail.com>
Co-authored-by: J Logan <john_logan@apple.com>
Co-authored-by: saehejkang <saehej.kang@gmail.com>
Co-authored-by: Anthony DePasquale <anthony@depasquale.org>
- Bump `containerization` to `0.25.0`
- Updates for parameter changes on containerization
registry access API.
- Updates for change to containerization
`cleanUpOrphanedBlobs` function.
ClientContainer was honestly extremely awkward. It could only be created
by passing either a ContainerConfiguration, or a Snapshot that had to be
obtained from calling a static method on the type itself. The type also
did not store a connection, so every single method got a new xpc
connection to the APIServer. This change aims to rework this type to be
just a generic client, that is *not* a client for one specific
container, but for any.
- Rename to ContainerClient
- Have list() return [ContainerSnapshot]
- Create a connection in the constructor
- Change all the callsites to use the new API
- Small, somewhat related, change to logs API in the APIServer. Now that
we don't need to call get() to grab a client anymore which was typically
what did "does this container exist" logic and gave a nice error
message, I added a small check in the APIServer to see if the container
exists and return mostly the same error message.
- Closes#1122.
- Adds placeholder ManagedResource and unit tests. Nothing is using
these yet.
- Adds system-defined resource labels for owning plugin and resource
role. The system discriminates the builtin network using role "builtin".
- Adds builtin role when creating builtin network at startup, and
ensures that a preexisting network with ID "default" gets updated with
the role label.
- Replace all network ID checks for "default" with the builtin role
check.
- Adds "builder" role to builder VM.
## Type of Change
- [ ] Bug fix
- [x] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
Role and owner labels should make cross-cutting resource policy easier
to implement.
## Testing
- [x] Tested locally
- [x] Added/updated tests
- [ ] Added/updated docs
## Summary
The `reload()` method in `PacketFilter.swift` references
`/sbin/reloadProcess` (the local variable name) instead of
`/sbin/pfctl`. This causes all DNS create and delete operations to fail:
```
Error: internalError: "pfctl reload exec failed: "Error Domain=NSCocoaErrorDomain Code=4 "The file "reloadProcess" doesn't exist.""
```
## Fix
One-line change: `/sbin/reloadProcess` → `/sbin/pfctl`
## Testing
Verified on macOS 26 (Tahoe) with Apple Silicon:
- `sudo container system dns create test.sdc.internal --localhost
203.0.113.1` succeeds without error
- Container can resolve and reach host services through the DNS redirect
- Closes#1113.
- This is the newest we can do until we address #767.
- Slight change to PacketFilter error handling so unit tests work more
reliably.
- Try making CLINetworkTests serialized to see if parallel execution is
causing flakes.
- Refer to #862
- Updated `SIZE` field to `FULL SIZE`, as it seemed more appropriate so
it does not get mixed up with the `descriptor size` field
- Closes#860
- Fixed#892.
- By contrast with `rm`, `prune` should display
the amount of reclaimed storage, so added code
to retrieve it.
Signed-off-by: ChengHao Yang <17496418+tico88612@users.noreply.github.com>
- Closes#977.
- Closes#1058.
- Prevents unexpected removal of containers on
bootstrapping and starting failures, by reorganizing
error handling for container `run`, `start`, and
`exec` so that error handling only unwinds that
which was done in the current scope.
- Relies on apple/containerization#495.
- Closes#1037.
- Adds a `--mode` flag that has `nat` and `hostOnly` options.
The host-only option selects the vmnet host-only mode,
where containers attached to the network can reach each
other and the host, but not external systems.
- Closes#346.
- This PR enables connecting host's localhost ports from
containers.
- It adds an option `--localhost <localhost>` to DNS
create command, after which the packets heading
ip address in container are redirected to localhost in
host machine. Packet filter rule is added and deleted
along with the creation and deletion of localhost domain.
This change adds --dns parameter support to the build command, matching
the existing functionality in the run command. This allows users to
specify custom DNS nameservers (like Google DNS 8.8.8.8) when building
container images, which is essential when the host machine uses a local
DNS resolver (e.g., 127.0.0.2) that doesn't work inside containers.
Changes:
- Added --dns option to BuildCommand to accept DNS nameserver IP
addresses
- Modified build logic to detect DNS configuration changes and recreate
the builder container when DNS settings differ
- Passed DNS configuration to BuilderStart.start() method
- Updated builder container creation to use specified DNS nameservers or
fall back to network gateway
## Type of Change
- [ ] Bug fix
- [X] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
This change adds --dns parameter support to the build command, matching
the existing functionality in the run command. This allows users to
specify custom DNS nameservers (like Google DNS 8.8.8.8) when building
container images, which is essential when the host machine uses a local
DNS resolver (e.g., 127.0.0.2) that doesn't work inside containers.
## Testing
- [X] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
---------
Co-authored-by: J Logan <sgtbakerrahulnet@yahoo.com>
- Facilitates #507, #642.
- Plumb logger with logger option access into every command.
- StderrLogHandler allows logging to be enhanced for ANSI color mode for
log levels, JSONL log output, replacing `--debug` with `--level level`.
- Global logger is now just an Application.swift fileprivate only used
for initial args processing.
- Log with timestamp at debug and trace level.
- Metadata output is crude at present; we can refine this in a
follow-up.
## Type of Change
- [x] Bug fix
## Motivation and Context
This PR changes the behavior of the Allocation Only vmnet network plugin
to use the default subnet in the fallback case if no subnet was
specified in the network configuration. This matches the behavior of
`ReservedVmnetNetwork`.
## Testing
- [x] Tested locally
Closes https://github.com/apple/container/issues/1050
If the sandbox svc exits out of band of the usual stop (or regular exit)
case the container svc's state is not properly updated for the
container. This was due to the cleanup steps involving trying to send
the shutdown rpc which cannot succeed as the sandbox svc does not exist
to service it.
To handle this, let's treat shutdown not returning successfully as
non-fatal (as this is mostly best effort), log an error and continue the
state cleanup.