- Replace `URL` with `FilePath` in `container copy` (#1557).
In addition, make `copyIn`/`copyOut` API to use `String` for path as we
need to preserve the trailing slash to the `LinuxContainer.copy`---i.e.,
this trailing slash is used in `LinuxContainer.copy` to determine copy
behavior.
## Type of Change
- [ ] Bug fix
- [x] New feature
- [ ] Breaking change
- [x] Documentation update
## Motivation and Context
Adds the `container copy` (aliased as `cp`) command to copy files
between a running container and the local filesystem.
I saw [#1023](https://github.com/apple/container/pull/1023) and the
feedback from @dcantah — the previous attempt relied on tar being
installed inside the container.
This implementation takes the recommended approach:
file transfers go through the guest agent via the existing
`copyIn`/`copyOut` methods on the core `Containerization`, with no
dependency on container tooling.
## Testing
- [x] Tested locally
- [x] Added/updated tests
- [x] Added/updated docs
---------
Co-authored-by: jwhur <57657645+JaewonHur@users.noreply.github.com>
- This change adds two types to support opaque runtime
data passing through the APIServer:
- RuntimeConfiguration `data`
- RuntimeLinuxData type
- LinuxRuntimeData defines runtime specific information.
With this change, it will support `variant` only. The
optional RuntimeConfiguration `data` field encodes
runtime specific data to pass through the APIServer.
It is decoded as needed by the runtime.
- The idea is to eventually move all runtime specific data
into the `data` field so that the APIServer is only aware
of generic container information.
- Closes#1517.
- Using URL for filesystem paths is bad practice. FilePath is safer and
more ergonomic.
- Sibling of #1480 (HostDNSResolver), same pattern.
- Discussion topic #1336.
- This change migrates away from using `UserDefaults`,
instead providing a TOML configuration mechanism for
user configurable settings. All existing system property
settings keys are supported in the new configuration
file. However, users will have to migrate any settings
they have configured in the `UserDefaults` into TOML
for these settings to take effect.
- Breaking changes:
* `container system property get` is removed in favor of
users directly utilizing `container system property list --format toml | jq<>`.
* `container system property set` is removed since the TOML
configuration is effectively immutable during the lifetime of the
`container` daemon. Uses can edit the TOML they have in their home
directory, however no changes will take effect until the daemon is
restarted via `container system stop && container system start`
* `container system property list --format table` is removed as
generating tabular format is non-trivial and the new TOML format is
intended to be human readable
- Part of #1404.
- Evolves API to use NetworkResource that conforms to ManagedResource.
- BREAKING CHANGE - compile time impact due to changes to Swift client
API signatures. No change to persistent data or API server XPC
protocols.
- Don't prefix match localhost, use exact
match only.
- Only check default local domain if one is
defined.
- Use IPv4Address for private IP CIDR tests.
- Closes#1439.
- May also address some cases of #1423.
- `_compressFile()` allocated a 1 MiB read buffer
per file but never freed it.
- It also treated InputStream.read() errors (-1) the
same as EOF (0), silently swallowing errors such
as TCC access denials under /Users/, which could
result in unexpected archive contents.
- Closes#1433.
- Renames `env` parameter to `dynamicEnv` to differentiate these
special-case environment variables from the standard container
environment.
- Use `[String: String]` instead of `[String: String]?`.
- Default to `[:]` when an down-revision client calls bootstrap without
supplying `dynamicEnv`.
This PR fixes#357, passing `SSH_AUTH_SOCK` env variable from current
terminal to the `SandboxService` so that the container can mount the
correct ssh auth socket. For that, it introduces `env` parameters to
`bootstrap` RPC of both `ContainersService` and `SandboxService`. This
parameter is used only for passing `SSH_AUTH_SOCK` now, but can be
extended to pass more runtime env variables.
This PR is a follow up PR of #1214.
## Type of Change
- [X] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Motivation and Context
Container run `--ssh` was inheriting `SSH_AUTH_SOCK` env variable from
launchd, not from current terminal.
## Testing
- [X] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
- Adds a color progress output mode (`--progress color`)
that renders ANSI-colored progress output with visual
differentiation between progress states.
- Like `ansi` mode, this feature requires a TTY.
- Closes#1366
- Part of #1404.
- COMPATIBILITY: Breaking change to client API. XPC protocol and
persistent data remain fully compatibile.
- Renames `ClientNetwork` to `NetworkClient`, aligning with
`ContainerClient`.
- Client uses instance methods instead of utility functions, with an
`init(serviceIdentifier:)` for the XPC service name. The value is
currently unused.
Closes#1352
Containerization has had support for a bit, it was just never brought
over here. It's exposed on the CLI via the classic `--cap-add` and
`--cap-drop` UX.
## Motivation and Context
This PR consolidates duplicated list-output formatting across the CLI
into shared rendering infrastructure.
Currently, each list command has its own copy of the same
json/quiet/table branching. This PR pulls that into shared rendering
infrastructure in `ContainerCommands`:
- `ListDisplayable` protocol for table + quiet output
- `renderJSON`, `renderTable`, `renderList` as pure functions that
return strings
- `emit()` as the single stdout boundary (no-ops on empty strings to
avoid blank-line regressions)
- `JSONOptions` so all JSON encoding goes through one path, including
volume inspect's pretty + ISO 8601 case
JSON encoding remains separate from display formatting: each command
still chooses its own JSON model, while `ListDisplayable` is used only
for table and quiet output. `ImageList` remains the intentional
exception for quiet mode so it can avoid unnecessary async work.
This change also replaces inline `JSONEncoder` usage with `renderJSON`,
removes the old `Codable+JSON.swift` helper, and moves `TableOutput` and
`ListFormat` into `ContainerCommands`. It also adds unit tests for the
shared rendering helpers and expands integration coverage for image,
network, and registry list formatting.
## Testing
- [x] Tested locally
- [x] Added/updated tests
- [ ] Added/updated docs
- Adds a `plain` progress output mode (`--progress plain`)
that outputs newline-separated progress lines without
ANSI escape sequences. This is useful for CI environments,
piped output, and non-TTY contexts where ANSI cursor
control is not supported. Unlike `--progress ansi`, plain
mode works even when stderr is not a TTY.
- Closes#1365
- Related: #641, #808
- Nothing uses this function, and it does not perform secure extraction.
Clients should instead use the `ArchiveReader` from the
ContainerizationArchive library.
- 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
- 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
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
- 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
## 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
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>
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.