Skip to content

Add TOML configuration for default DNS nameservers, search, options - #1614

Merged
jglogan merged 5 commits into
apple:mainfrom
0xMH:fix/1449-dns-defaults
Nov 3, 2026
Merged

jglogan merged 5 commits into
apple:mainfrom
0xMH:fix/1449-dns-defaults

Conversation

@0xMH

@0xMH 0xMH commented May 28, 2026 •

Copy link
Copy Markdown
Contributor

Type of Change

  • New feature

Motivation and Context

Closes #1449. Adds default values for --dns, --dns-search, --dns-option, and --dns-domain to the [dns] section of ~/.config/container/config.toml, so users hitting macOS mDNSResponder conflicts can set the workaround once instead of repeating it on every invocation. Depends on the merged TOML configuration introduced by #1425.

Defaults are read by container run, container build, and container builder start via a shared Utility.dnsConfiguration(from:defaults:) helper. CLI flags take precedence; --no-dns still disables DNS. Two pre-existing bugs in the build path were fixed to make the feature work end-to-end: BuildCommand was forwarding only dnsNameservers to the builder (now forwards all four DNS fields), and BuilderStart's dnsChanged check only compared the first non-empty field (now compares all four).

Testing

  • Tested locally
  • Added/updated tests
  • Added/updated docs

@0xMH
0xMH force-pushed the fix/1449-dns-defaults branch 2 times, most recently from 6af7693 to b010238 Compare May 31, 2026 22:56
@0xMH
0xMH requested a review from katiewasnothere June 1, 2026 18:45
@github-actions

github-actions Bot commented Jun 2, 2026 •

Copy link
Copy Markdown

Code Coverage

Tier Line Coverage
Unit 23.1%
Integration 69.4%
Combined 78.13%

@0xMH
0xMH force-pushed the fix/1449-dns-defaults branch 2 times, most recently from 3eb0a7e to 46bd18b Compare June 3, 2026 23:29
@0xMH

0xMH commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @katiewasnothere. Happy to iterate further if anything else needs addressing.

@katiewasnothere katiewasnothere added this to the 2026-06 milestone Jun 3, 2026
@katiewasnothere

Copy link
Copy Markdown
Contributor

Hi @0xMH thank you for all the work you've done on this change! We are planning to make a new release of the container package some time in the next week and we want to hold off on merging this change until then.

@am-saksham

Copy link
Copy Markdown

Hi @0xMH and @katiewasnothere! First, thanks for the great work figuring out the core logic for this.

I noticed this PR has been stalled since the June release and has picked up some merge conflicts. I also saw that a couple of newer PRs for #1449 were opened recently, but they seem to have missed the [dns] vs [container.dns] architectural requirement that Katie pointed out above.

@0xMH, if you are currently swamped with other things, would you mind if I pull your branch, resolve the conflicts against main, and open a fresh PR to get this over the finish line? I will carry over your commits and make sure to include a Co-authored-by tag so you keep full credit for your work.

Let me know if that sounds good!

@0xMH

0xMH commented Jul 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the offer! but no need since I'm waiting for the green flag to continue and rebase and prepare for the merge.

@am-saksham

Copy link
Copy Markdown

Awesome, sounds good! Looking forward to seeing it merged. Let me know if you end up needing a hand later on!

@jglogan jglogan removed this from the 2026-06 milestone Jul 7, 2026
@katiewasnothere

Copy link
Copy Markdown
Contributor

@0xMH Really sorry for the delay here, we've been swamped. I'd love to get this in for this sprint (which ends at the end of August). Could you rebase your PR? I will take another pass through the code. Thank you for your work here!

Comment thread docs/command-reference.md Outdated
- `192.168.*.*`
- `172.16.*.*` through `172.31.*.*`
- The host ends with the machine's default container DNS domain (as defined in `DNSConfig.defaultDomain`, located [here](../Sources/ContainerPersistence/ContainerSystemConfig.swift))
- The host ends with the machine's configured internal DNS domain from `[dns].domain`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a link to the reference doc here instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment is now not relevant because the documentation was reorganized in PR #2032. The DNS settings are now documented here right?

public static func dnsConfiguration(
from flags: Flags.DNS,
defaults: ContainerDNSConfig,
hostDomainFallback: String? = nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This to preserve the existing behavior. hostDomainFallback uses [dns].domain only when no --dns-domain flag or [container.dns].domain is set. I added tests for the fallback and for container specific override

Comment on lines +155 to +157
public let nameservers: [String]
public let searchDomains: [String]
public let options: [String]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about making these optionals instead of empty arrays?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I made them optional.


public let cpus: Int
public let memory: MemorySize
public let dns: ContainerDNSConfig

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about making this an optional as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I made ContainerConfig.dns optional as well.

@jglogan

jglogan commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

@0xMH I'm Scrubbing through some of the PRs that fell through the cracks. When you can, can you rebase and address the PR review feedback? Thanks!

@0xMH
0xMH force-pushed the fix/1449-dns-defaults branch 2 times, most recently from 606c4d4 to 5b9e784 Compare October 6, 2026 07:07
@0xMH

0xMH commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

I rebased the branch and addressed the comments. Please let me know if there’s anything else to address.

@jglogan

jglogan commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

@0xMH Sorry, looks like you'll need to do one more rebase. The builder got extracted to a plugin so your changes there will need to move over to the new locations.

@0xMH

0xMH commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

Sure, Will do that maybe tomorrow.

@0xMH
0xMH force-pushed the fix/1449-dns-defaults branch from 5b9e784 to 9e5041b Compare October 15, 2026 19:04
@0xMH

0xMH commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Rebased nw.

@jglogan jglogan added this to the 26w44 milestone Nov 2, 2026
@jglogan

jglogan commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

@0xMH Thanks for your contribution and patience! Merged.

@jglogan
jglogan merged commit 60569e5 into apple:main Nov 3, 2026
3 checks passed
henrywang added a commit to henrywang/Berthly that referenced this pull request Nov 12, 2026
….0 (#238)

Closes #231. Closes #232.

Moves Berthly's `container` pin from 1.6.1 to 1.7.1, and
`containerization` from 0.53.0 to 0.54.0. No other package moved. 1.7.1
is the first 1.7 release (1.7.0 was tagged but never published).

## Why

- **Builds with builder shim 0.13.3.** The pin also moves the builder
shim from 0.13.2 to 0.13.3 (apple/container#2434). 0.13.3 is built with
gRPC-Go v1.84.0, which rejects requests without an `:authority`
(grpc/grpc-go#9365). apple/container#2428 adds one in `ContainerBuild`,
which Berthly links, so the shim and the fix arrive together here.
- **Build steps that need the whole context.** apple/container#2414: an
empty `followpaths` now means the whole context instead of nothing.
- **`[container.dns]` defaults** (apple/container#1614) reach Run/Create
through `Utility.containerConfigFromFlags`. The builder side is #233.

## Changes

- `project.pbxproj`: `minimumVersion = 1.7.1` (`upToNextMinorVersion`).
- `Package.resolved`: `container` 1.7.1, `containerization` 0.54.0.
- `ContainerCompatibility`:
- `requiredVersion = "1.7.1"`: every 1.6.x daemon hits the upgrade gate
(#232, option 1).
- `patchFloor` becomes `String? = nil` rather than being removed, so the
mechanism and its tests stay for the next known-bad patch.
  - New `requiredVersionRationale`.
- `shippedFloorBlocksContainer160` becomes
`shippedGateBlocks16xAndAccepts171`.

No compile breaks. `ContainerListFilters.withoutMachines()` was removed
upstream, but Berthly doesn't call it. The new defaulted `Builder.start`
parameters don't affect it either, since Berthly uses its own replica
(#210).

The 1.7.1 pkg and the `container` binary are still signed by `Apple Inc.
- Containerization (UPBK2H6LZM)`, so the installer's signature check
still accepts them.

## Testing

All local, on Xcode 27.2 with a container 1.7.1 daemon and the 1.7.1
recommended kernel (Kata 4.3.1, `vmlinux-6.18.56-208-debug`):

- `swiftlint lint --strict`: clean
- BerthlyTests: 611 passed
- BerthlyUITests (mock): 85 passed, 2 skipped (App Intents tests, which
need a team-signed runner)
- E2E via `scripts/e2e.sh`: 28/28 passed. Covers Dockerfile builds,
SSH-forwarded builds, a machine-image build plus boot, a registry
build/push/pull round trip, and machine first boot. After the run, the
`buildkit` container is on `builder:0.13.3`.

## Follow-ups (milestone v1.7.1)

#233 builder DNS defaults, #234 System page `container.dns.*` rows, #235
CPU % unit decision, #236 PARITY.md re-audit, #237 remaining real-daemon
checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
henrywang added a commit to henrywang/Berthly that referenced this pull request Nov 12, 2026
…ilder (#239)

Closes #233.

## Problem

`LiveContainerService.startBuilderContainer` is Berthly's copy of
upstream's `Builder.start`, kept separate on purpose (#210). Two things
diverged from the CLI:

- **Builder DNS has been hard-coded to `1.1.1.1` since the initial
commit.** It set `config.dns = DNSConfiguration()`, and that init's
default nameserver is `1.1.1.1`. Upstream has always passed empty
nameservers, which the runtime replaces with the network gateway's
resolver (`RuntimeService`: "Dynamically configure the DNS nameserver
from a network if no explicit configuration"). So `RUN` steps in Berthly
builds skipped the gateway resolver, which the CLI's builds use.
- **`[container.dns]` defaults were ignored.** container 1.7.1
(apple/container#1614) applies these `config.toml` defaults to the
builder. Berthly's Run/Create picked them up with #238, but its builder
didn't.

## Changes

- New `builderDNS(defaults:)` resolves DNS exactly as upstream's builder
does: `[container.dns]` defaults, else empty nameservers, with no
host-domain fallback.
- It uses the four-argument `Flags.DNS` init. The empty init leaves the
`@Option`s in ArgumentParser's unset `.definition` state, the same trap
as `Flags.MachineUser`. This differs from the task text in #233.
- DNS joins `builderNeedsRecreate`.
- A missing DNS block is compared as `.init()` (`1.1.1.1`), copying
upstream's `dnsConfigurationChanged`, so a CLI build and a Berthly build
don't recreate each other's builder. #233's task text expected "no
change" there; this matches upstream instead.
- Tests: four DNS-field recreate cases, a missing-DNS case, and
`BuilderDNSTests` for nil, full and partial defaults.

## Behavior change

- **Builds now resolve through the gateway (`192.168.64.1`) by default
instead of `1.1.1.1`, matching `container build`.** Builds behind a VPN
or split DNS may resolve differently.
- **The first Berthly build after updating recreates an existing builder
once,** because it was made with `1.1.1.1`. That drops the build cache.

## Testing

Local, container 1.7.1 daemon:

- `swiftlint lint --strict`: clean
- BerthlyTests: 619 passed (8 new)
- E2E via `scripts/e2e.sh`:
  - `ResourceJourneyTests/testBuildImageFromDockerfileThenRun` (×5)
  - `testBuildWithSSHForwardingMountsAgentSocket`
  - `MachineJourneyTests/testBuildMachineImageThenBootMachine`
- I watched the `buildkit` container's `startedDate` and stored `dns`
across runs:
1. A builder from before this PR (`['1.1.1.1']`) was recreated once on
the first build, now with `[]`. The second build reused it.
2. A CLI `container build`, then a Berthly build: no recreate either
way. The CLI build's `RUN cat /etc/resolv.conf` printed `nameserver
192.168.64.1`.
3. With `[container.dns]` (`nameservers = ["9.9.9.9"]`, `searchDomains =
[...]`) set and the daemon restarted, the builder was recreated with
those values, and its `/etc/resolv.conf` matched. After restoring the
config, the builder went back to `[]`.
- The daemon stores `nameservers: []` and only fills in the gateway
inside the guest, so the comparison doesn't recreate the builder on
every build. I confirmed this with a plain `container run` plus
`inspect`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
henrywang added a commit to henrywang/Berthly that referenced this pull request Nov 12, 2026
…240)

Closes #234.

container 1.7.1 added a `[container.dns]` section to `config.toml`
(apple/container#1614), and `container system property list` shows it.
Berthly's System page builds its own list in
`LiveContainerService.mapSystemProperties`, which had no rows for the
new section.

## Changes

- Four rows after `container.memory`, matching where the CLI's TOML puts
the subsection: `container.dns.domain`, `container.dns.nameservers`,
`container.dns.searchDomains`, `container.dns.options`.
- An unset value shows as the existing em dash. An empty list does too,
because for `[container.dns]` it means the same as unset: the runtime
falls back to the network gateway's resolver.
- Lists show comma-separated (`10.0.0.53, 10.0.0.54`). The issue
suggested TOML array syntax, but no other row on the page uses TOML
quoting (`dns.domain` shows `test`, not `"test"`).
- The mock fixture gets the same rows with sample values.
- Not done: the issue's optional idea of showing these defaults as
placeholders in the Run sheet's DNS fields.

## Testing

- `swiftlint lint --strict`: clean
- BerthlyTests: 622 passed, 3 of them new (all dashes when unset,
configured values shown, row order)
- E2E: `SystemViewJourneyTests/testSystemPropertiesDisclosureExpands`
passed

🤖 Generated with [Claude Code](https://claude.com/claude-code)
henrywang added a commit to henrywang/Berthly that referenced this pull request Nov 12, 2026
Closes #236.

Re-audits PARITY.md against container CLI 1.7.1, following #217 for
1.6.1. 1.7.1 changed no CLI flags outside `cluster` (diffed
`ContainerCommands`, `Flags.swift`, and the cluster plugin between 1.6.1
and 1.7.1).

## Changes

- **Header:** "Audited against" moves to 1.7.1 (2026-11-12).
- **`stats`:** CPU is a percentage of one core, the CLI's
`cpuUtilization` × 100 (#235).
- **Run/Create:**
- Empty DNS fields fall back to `[container.dns]`
(apple/container#1614), and a value in the sheet overrides them.
- Out-of-range cpus or memory get the CLI's own error, since 1.7.1
validates both on the client.
- **Builder:** gets the `[container.dns]` defaults, or the gateway's
resolver, and is recreated when its DNS changes (#233).
- **`property`:** the list includes the `container.dns.*` defaults
(#234).
- **`cluster` (deliberate gap):**
- Records the 1.7.1 changes: `load-image` replaced by
`--shared-image-store` (apple/container#2437), `cluster ls` per cluster
with `--nodes` (apple/container#2451), and per-worker cpus/memory
(apple/container#2448).
- Notes that the CLI now skips cluster nodes in
`ls`/`start`/`stop`/`kill`/`delete`/`prune` (apple/container#2462), as
Berthly already did (#204). `prune` isn't in #236's list, but the 1.7.1
source filters it too.
- The revisit condition is half met: the new `container-core-clusters`
XPC service only handles cluster records, and the command is still
EXPERIMENTAL.

Time Machine exclusion (apple/container#2412) and the smaller install
(apple/container#2458) are daemon-side with no CLI command to compare
against, so they get no entry.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
andrewkomkov added a commit to getgantry/gantry that referenced this pull request Nov 12, 2026
Apple container **1.7.1** is out. The previously tracked version is
`1.6.1`.

Upstream notes: https://github.com/apple/container/releases/tag/1.7.1. A
copy is in `docs/upstream/apple-container-1.7.1.md`.

Most of the 1.7.1 support is already on main from PR #57
(`specs/001-apple-container-1-7-1`) and PR #50 (clusters). This PR adds
no code. It adds the 1.7.1 features to the README and records the live
check in spec 001.

## Review checklist

- [x] New or changed CLI flags Gantry should surface: `cluster run
--shared-image-store` and `--workers count=,cpus=,memory=` came in PR
#50. The `run`, `create`, `machine` and `build` commands have no new
flags in 1.7.1.
- [x] Changed `--format json` shapes the DockerKit apple transport
decodes: only `stats` changed (`cpuUtilization`).
`AppleContainerJSON.statsBody` uses it, with the counter math as
fallback
(`Packages/DockerKit/Sources/DockerKit/AppleContainer/AppleContainerJSON.swift:653`).
The live output matches the test fixture. `container ls --format json`
did not change.
- [x] Fixed upstream bugs Gantry currently works around: none. The
BuildKit fixes (#2428, #2414) need no change in Gantry. The "Builder
image is outdated" card covers the new builder shim 0.13.3
(`AppleBuilderStatus.imageUpdate`).
- [x] `ContainerTooling.recommendedVersion` and feature gates:
`recommendedVersion = "1.7.1"`
(`Packages/AppCore/Sources/AppCore/ContainerTooling.swift:18`). The DNS
defaults are gated on 1.7.0 (`containerDNSDefaultsVersion`, line 46).
- [x] MCP tools and App Intents that expose the affected commands:
`container_stats` uses the same DockerKit decoder. `apple_set_property`
accepts lists for the DNS keys (PR #57). No App Intent shows the changed
commands.
- [x] README and CHANGELOG entries for whatever is adopted: the
CHANGELOG has the #57 and #50 lines. This PR adds the 1.7.1 features to
the README.

## Adopted (on main, checked again on CLI 1.7.1)

- Stats `cpuUtilization` (#2146). The old calculation stays as fallback
for 1.6.1.
- `[container.dns]` defaults in `config.toml` (#1614): a list editor in
System Properties, gated on 1.7.0.
- Recommended kernel (#2447): Gantry has no kernel version of its own.
It runs `system kernel set --recommended`.
- Cluster changes (#2437, #2448, #2451, #2462) came in PR #50. The
notice for missing or stopped cluster services came in PR #57.
- Builder shim 0.13.3: the outdated builder card.

## Not adopted, and why

- #2412 Time Machine exclusion, #2443 containerization 0.54.0, #2458
package size, #2470 copy blobs, #2416 bootstrapper, #2477 test library:
internal changes. Gantry has nothing to show for them.
- #2457, #2459, #2433, #2413: upstream docs and examples only.

## Checks

- `swift test` in DockerKit: 324 tests passed. AppCore
`AppleContainer171` tests: 19 passed.
- `scripts/check-localization.py`: 0 problems in 28 languages. This PR
adds no strings.
- Debug build on CLI 1.7.1: a busy test container shows 98 % CPU. The
CLI reports `cpuUtilization` 1.0 for it.
- The Builder card shows 0.13.2 to 0.13.3 in light and dark mode. System
Properties shows `[container.dns]`. The cluster list shows one row for
each cluster.
- Open (T035 in spec 001): two items had no check in the app. These are
the DNS list editor sheet and the cluster services notice. The editor
needs a click. The notice needs a broken cluster setup.

---

<details><summary>Upstream release notes</summary>

## Highlights

⌨️ denotes breaking CLI changes.

👩‍💻 denotes breaking API changes.

- Core
- [`container stats` now reports `cpuUtilization` in JSON, YAML, and
TOML output](apple/container#2146)
- [Image snapshots and container filesystems are now excluded from Time
Machine backups](apple/container#2412)
- [Default Kata kernel is now 4.3.1
(`vmlinux-6.18.56-208-debug`)](apple/container#2447)
- [Updated Containerization to
0.54.0](apple/container#2443)
- Networking
- [Default DNS nameservers, search domains, and options can now be set
in `config.toml`](apple/container#1614)
- Build
- [Fixed `container build` failures with newer
BuildKit](apple/container#2428) and [missing
build context for steps that need the full
context](apple/container#2414)
- Kubernetes
- ⌨️ [New `--shared-image-store` option on `container cluster run` to
use the `container` image store from cluster nodes; removed the
`load-image` subcommand](apple/container#2437)
- ⌨️ [`container cluster ls` now shows one row per cluster; use
`--nodes` for the per-node
view](apple/container#2451)
- ⌨️ [Container lifecycle commands no longer operate on cluster
nodes](apple/container#2462)
- [Worker node CPU and memory can now be set with `--workers
count=<n>,cpus=<n>,memory=<size>`](apple/container#2448)

## What's Changed
* Send an :authority on the builder gRPC connection by @jglogan in
apple/container#2428
* Adds `container cluster` example. by @jglogan in
apple/container#2433
* Update container-builder-shim to 0.13.3. by @jglogan in
apple/container#2434
* use macos 27 runners by @madrob in
apple/container#2436
* Fix empty followpaths handling in BuildFSSync by @onlyarnav in
apple/container#2414
* Document container clean in the reclaim disk space guide by
@lucasbrito-wdt in apple/container#2413
* Bump to use containerization 0.54.0 by @adityaramani in
apple/container#2443
* feat(stats): report cpuUtilization in the machine-readable formats by
@guanchzhou in apple/container#2146
* [k8s plugin] Create a cluster bootstrapper by @katiewasnothere in
apple/container#2416
* Update recommended kernel to kata 4.3.1 release
vmlinux-6.18.56-208-debug by @katiewasnothere in
apple/container#2447
* Add TOML configuration for default DNS nameservers, search, options by
@0xMH in apple/container#1614
* Add the ability to share container's image store with container
cluster by @crosbymichael in
apple/container#2437
* Reduce install package size and install footprint. by @jglogan in
apple/container#2458
* Add reference to apple/container-examples and remove examples/ out of
this repo by @michaelzhang114 in
apple/container#2457
* Create container-core-clusters XPC service by @adityaramani in
apple/container#2451
* Exclude recreatable container data from Time Machine by @abdullahtas0
in apple/container#2412
* Clean the `cluster-shim` build files with `make clean` by @dkovba in
apple/container#2463
* Quiet the `cluster-shim` build output and show the swift progress in
place by @dkovba in apple/container#2461
* Do not allow high level container lifecycle commands to operate on
cluster nodes by @katiewasnothere in
apple/container#2462
* Switch to copy blobs by @crosbymichael in
apple/container#2470
* Add option to set cpus and memory resources for worker nodes of
cluster by @katiewasnothere in
apple/container#2448
* Removed bug-report-how-to.md as this info is now consolidated in
CONTRIBUTING.md by @michaelzhang114 in
apple/container#2459
* Move HostStoreServer into a library so tests don't link the executable
by @katiewasnothere in apple/container#2477

## New Contributors
* @madrob made their first contribution in
apple/container#2436
* @onlyarnav made their first contribution in
apple/container#2414
* @lucasbrito-wdt made their first contribution in
apple/container#2413
* @abdullahtas0 made their first contribution in
apple/container#2412

**Full Changelog**:
apple/container@1.6.1...1.7.1

</details>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: andrewkomkov <33517893+andrewkomkov@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Request]: system property for default --dns.

4 participants