Commit Graph
225 Commits
Author SHA1 Message Date
Danny Canter 8a34763e40 Socket: Add fd receiving (#330)
Via scm_rights. Useful for supporting spawning runc as an OCI runtime as
that's how the pty is passed to the client.
2025-10-14 15:59:56 -07:00
Danny Canter 91ef4009a3 Integration: Lower default concurrency (#331)
I only see a very small delta halving this (.6 seconds), and the default
will likely stress the CI machines a lot more. This change also swaps
the atomic increments to .relaxed, as there's no ordering required, just
need no torn writes.
2025-10-14 12:55:10 -07:00
Santosh Bhavani 87e8fd1673 Add configurable concurrent layer downloads (#311)
Adds `maxConcurrentDownloads` parameter to `ImageStore.pull()`.

Performance improvement: ~1.2-1.3x faster pulls for multi-layer images
with higher concurrency.

Signed-off-by: Santosh Bhavani <santosh.bhavani@live.com>
2025-10-13 22:29:12 -07:00
Kathryn Baldauf e283e023ab Use container's environment when starting the init process (#329)
Fixes an issue first described in
https://github.com/apple/container/issues/740.

Previously the initial process of the container was using vminitd's
environment variables to find the target executable. This PR updates the
code to use the container's configured environment for the initial
process instead. The behavior of an exec in a container should be the
same as before.

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2025-10-13 21:33:18 -07:00
Danny Canter 6e96cdb3a0 Integration: Run tests concurrently (#326) 2025-10-10 11:02:58 -07:00
Danny Canter d0383eb5bf LinuxContainer: AsyncMutex-ify LinuxContainer (#325)
This change moves LinuxContainer to use the new AsyncMutex type. This allows us to keep using our old state machine model, but lock around the entirety of operations. This also allows us to axe quite a few states that were intermediary states only there to protect against multiple threads calling (even if it was unlikely..) the same method at the same time (.creating, .starting, .stopping etc.).

The rationale is: Mutex is somewhat tricky to use as you can't (for good reason) do any async work inside the closure. This makes some of our work difficult as every single interaction with the guest is via an rpc, which is all async. There really isn't a worry about contention, because most container methods will only ever be invoked once (create, start, stop) so a big heavy lock isn't much of a deterrent.
2025-10-09 15:09:53 -07:00
Danny Canter 40727e49ba Vminitd: Write cgroup limits (#322)
Fixes #320

Today we don't actually setup any cgroup limits, as because there's a
1-1 mapping from container<->vm we can just use the VMs resources as the
limit (can't use more than 1GB if that's all the guest sees :) ).
However, if we ever supported > 1 container in the guest it'd be
necessary to actually setup the cg limits. This change just sets a
memory limit and cpu toggles to match whatever was specific for the
container.
2025-10-09 16:03:40 -04:00
Danny Canter d18d1186a2 ContainerizationExtras: Add AsyncMutex (#324)
We already have `AsyncLock`, but in some cases it'd be nice to have the
type protect a piece of data that you access through the lock, much like
the Synchronization frameworks new `Mutex` type.

This change adds such a type.
2025-10-09 10:47:35 -04:00
J Logan 2443a245cb Fixes proxy logic in RegistryClient. (#314)
- Closes #255.
- Fixes ProxyUtils so that the environment variable to be used for proxy
selection is determined by the request scheme.
- RegistryClient uses ProxyUtils to get the proxy URL used by the
HTTPClient.
- Tweak hostname resolution error message to avoid misleading output if
the proxy hostname cannot be resolved.
2025-10-09 10:30:49 -04:00
Danny Canter 06d3a37f8d Add support for container statistics (#318)
Closes #138

This rounds up cgroup and network stats (via netlink) and exposes them
via an agent rpc and on LinuxContainer. While this is not an entirely
accurate view into the full resources being used by the container given
the virtualized nature (doesn't account for vcpu, device etc overhead)
it should give an accurate overview of the workload resource usage in
the guest.

This change besides the stated goal also removes the interfaceStatistics
rpc and just moves these network stats into the new containerStatistics
one. Related to that, it also renames the InterfaceStatistics struct to
NetworkStatistics and moves this into ContainerStatistics as a nested
struct.
2025-10-08 10:09:10 -04:00
Eric Ernst 85de8fc0c5 make: fix coverage target (#313)
Address capitalization error

Signed-off-by: Eric Ernst <eric_ernst@apple.com>
2025-10-06 11:16:14 -07:00
Danny Canter 996cdceae0 Update InterfaceStatistics.swift license header (#310)
Checked in before the all rights reserved was removed shortly after.
2025-10-05 15:02:48 -07:00
J Logan 995a231348 Removes "all rights reserved" from license header. (#309) 2025-10-03 13:27:59 -07:00
Danny Canter 80e2813bcf Netlink: Add stats support (#308)
Adds support for grabbing stats for an iface. This will be surfaced in a
coming change to get container level statistics from the guest, where
one field will be network stats.
2025-10-03 12:53:35 -07:00
Eric Ernst f9ae8f7801 make: add coverage target (#307)
Add coverage target for getting csv code-coverage output

Signed-off-by: Eric Ernst <eric_ernst@apple.com>
2025-10-03 01:43:11 -07:00
Danny Canter 183255ee0e Vminitd: Add cgroup stats support (#306)
This is not wired up to anything right now, but it will be used for
implementing stats gathering on the host via an rpc in the future. I've
left off the rpc portion as this is already a decent amount to review.
2025-10-01 11:26:45 -04:00
Dmitry Kovba b331d29959 Update an issue template (#304)
This PR adds the default value "N/A" to the logs section to prevent it
from being empty in most issues.
2025-10-01 11:24:31 -04:00
Danny Canter 28892cfa11 Kernel: Fix make (#301)
Fixes #296

Today the kernel subdirectory is somewhat useless. The dockerfile we had
tried to use an image that isn't actually on ghcr, so everything would
kind of just crap out. This change swaps things so that we build a local
image that has all the bits needed to compile the kernel, and then uses
that image to build the resulting kernel and plop it in the current
working directory. This change does add a reliance on `container` being
installed however, but for folks that need to build a custom kernel this
doesn't seem like too much of an issue to me.
2025-09-30 18:48:20 -07:00
J Logan 992ed9f5aa Adds public init for ExitStatus. (#305)
Client code may want to return ExitStatus from
functions that return a containerization process
return code, or -1 for caught exceptions.
2025-09-30 17:57:26 -07:00
Michael Crosby cb6b78f580 dns config should have options not opts (#303)
Signed-off-by: crosbymichael <michael_crosby@apple.com>
2025-09-29 16:35:58 -04:00
J Logan b61b932adf Adds --add-file to allow adding files to initfs. (#302)
- Motivation is to be able to add the `swift-backtrace-static` binary as
needed.
- Use singlular `--add-file` and `--label` options since both accept
multiple invocations with single values each.

Example usage:

```bash
./bin/cctl rootfs create \
                --vminitd vminitd/bin/vminitd \
                --vmexec vminitd/bin/vmexec \
                --add-file /Users/john/.swiftpm/swift-sdks/swift-6.2-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.2-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/aarch64/usr/libexec/swift/linux-static/swift-backtrace-static:sbin/swift-backtrace \
                --label org.opencontainers.image.source=https://github.com/apple/containerization \
                --image vminit:latest \
                bin/init.rootfs.tar.gz
```
2025-09-29 12:38:45 -07:00
Danny Canter 82f2d887dd LinuxContainer/LinuxProcess: Have wait return ExitStatus (#300)
Have wait return a struct containing the exit code and the time at which
the process actually exited. This is useful so higher level tools (like
container) don't need to craft a date themselves, and it will be more
accurate as it's taken in the guest directly after the process exits.
2025-09-29 14:09:37 -04:00
Euan Harris 511dd59e19 Remove accidental dependency on NIOFileSystem (#298)
swift-nio's public export of NIOFileSystem was removed in 2.86.1:
https://github.com/apple/swift-nio/pull/3370

NIOFileSystem was not yet supposed to be public, but _NIOFileSystem
depended on it as a public import. This made it possible for
`containerization` to see the `NIOFileSystem` package by accident.

Replacing the use of `NIOFileSystem` by `_NIOFileSystem`, as used
elsewhere, fixes the problem.

## Why does CI currently pass?

The change in `swift-nio` does not currently cause `containerization`'s
CI to fail because `Package.resolved` pins `swift-nio` to 2.83.0, before
the change was made. New versions of upstream dependencies will not be
tested until `Package.resolved` is explicitly updated.

When containerization is built as a dependency of a end-user project,
its `Package.resolved` file is ignored. Instead, the dependency
constraints from containerization's Package.swift file are combined with
those of the project and any other library dependencies, so SwiftPM or
Xcode can find a set of mutually compatible packages. This can lead to
new versions of containerization's upstream dependencies being used,
even though those versions have never been tested in CI.

The build failure can be demonstrated by creating a new package which
depends on `containerization` but does not constrain package versions:
```
    % swift package init --type executable
    Creating executable package: test
    Creating Package.swift
    Creating Sources
    Creating Sources/test/test.swift
    % cat > Package.swift <<EOF
    heredoc> // swift-tools-version: 6.2
    // The swift-tools-version declares the minimum version of Swift required to build this package.

    import PackageDescription

    let package = Package(
        name: "test",
        platforms: [
            .macOS(.v26),
        ],
        dependencies: [
            .package(url: "https://github.com/apple/containerization", from: "0.7.2"),

        ],
        targets: [
            // Targets are the basic building blocks of a package, defining a module or a test suite.
            // Targets can depend on other targets in this package and products from dependencies.
            .executableTarget(
                name: "test",
                dependencies: [
                    .product(name: "Containerization", package: "containerization"),
                ]
            ),
        ]
    )
    EOF
    % swift build
    ...
    /private/tmp/test/.build/checkouts/containerization/Sources/ContainerizationOCI/Client/RegistryClient+Fetch.swift:25:8: error: no such module 'NIOFileSystem'
     23 |
     24 | #if os(macOS)
     25 | import NIOFileSystem
        |        `- error: no such module 'NIOFileSystem'
     26 | #endif
     27 |
```
2025-09-23 09:52:29 -07:00
Danny Canter 654894d3b0 Bump swift version and sdks to released 6.2 (#297) 2025-09-23 10:25:10 -04:00
Eric Ernst 51ef9f81fe examples: add ctr-example (#295)
Add very basic example of running a Linux container using
Containerization

Signed-off-by: Eric Ernst <eric_ernst@apple.com>
2025-09-19 02:13:54 -07:00
Danny Canter 898e3ae6be LinuxContainer: Stop should be idempotent (#291)
I think stop should be able to be called more than once and not
complain.
2025-09-18 11:17:42 -07:00
Sidhartha Mani fe227c805e Add IO utilities for traversing dirs and reading files from EXT4 devices (#285) 2025-09-18 09:03:26 -07:00
Ryan Govostes d7613c4830 Remove redundant kernel-build directory (#292)
The project has `kernel-build/` and `kernel/image/` which contain the
same files:

```
$ diff -ru kernel/image/ kernel-build/
# no output
```

I did not find any reference to `kernel-build/` in any workflow or
README or Makefile, so I removed it in favor of `kernel/image/`.
2025-09-18 10:43:32 -04:00
Danny Canter 13e74cd99a Vminitd: Remove some fatalError's (#290)
No reason they need to be as destructive.
2025-09-18 10:42:15 -04:00
Michael Crosby 8bcd77173b only return arm64 for proper 64 architectures (#293)
Signed-off-by: crosbymichael <michael_crosby@apple.com>
2025-09-18 10:40:50 -04:00
Danny Canter f3641e67cb Undo accidental revert of commits (#289)
#288 accidentally reverted #282 and #284.
2025-09-13 17:37:15 -07:00
Harry LiandDmitry Kovba 5fbae0e590 feat: add proxy utility (#288)
Signed-off-by: Harry Li <harrymingh@gmail.com>
Co-authored-by: Dmitry Kovba <dkovba@apple.com>
2025-09-12 11:23:41 -07:00
Dmitry Kovba 31bfef4a8e Print the Swift version before building (#286)
With the changes in this PR, we'll print the Swift version before
building. This mirrors a similar change in container, introduced in
https://github.com/apple/container/pull/550.
2025-09-11 10:17:24 -07:00
Dmitry Kovba a41dbd4671 Update the toolchain and Static Linux SDK (#287)
The PR updates the toolchain and Static Linux SDK. This resolves the
compilation errors below:

```
Building vminitd and vmexec...
Building for debugging...
<unknown>:0: error: stack nearly exhausted; compilation time may suffer, and crashes due to stack overflow are likely
<module-includes>:1:10: note: in file included from <module-includes>:1:
1 | #include "SwiftMusl.h"
  |          `- note: in file included from <module-includes>:1:
2 | 

/Users/Dmitry/Library/org.swift.swiftpm/swift-sdks/swift-6.2-DEVELOPMENT-SNAPSHOT-2025-06-25-a_static-linux-0.0.1.artifactbundle/swift-6.2-DEVELOPMENT-SNAPSHOT-2025-06-25-a_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/aarch64/usr/lib/swift_static/linux-static/aarch64/SwiftMusl.h:135:10: error: could not build module 'sys_stropts'
133 | #include <sys/signalfd.h>
134 | #include <sys/statfs.h>
135 | #include <sys/stropts.h>
    |          `- error: could not build module 'sys_stropts'
136 | #include <sys/swap.h>
137 | #include <sys/syscall.h>

<unknown>:0: error: stack nearly exhausted; compilation time may suffer, and crashes due to stack overflow are likely
<unknown>:0: error: could not build C module 'SwiftMusl'
<unknown>:0: error: stack nearly exhausted; compilation time may suffer, and crashes due to stack overflow are likely
<module-includes>:1:10: note: in file included from <module-includes>:1:
1 | #include "SwiftMusl.h"
  |          `- note: in file included from <module-includes>:1:
2 | 

/Users/Dmitry/Library/org.swift.swiftpm/swift-sdks/swift-6.2-DEVELOPMENT-SNAPSHOT-2025-06-25-a_static-linux-0.0.1.artifactbundle/swift-6.2-DEVELOPMENT-SNAPSHOT-2025-06-25-a_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/aarch64/usr/lib/swift_static/linux-static/aarch64/SwiftMusl.h:135:10: error: could not build module 'sys_stropts'
133 | #include <sys/signalfd.h>
134 | #include <sys/statfs.h>
135 | #include <sys/stropts.h>
    |          `- error: could not build module 'sys_stropts'
136 | #include <sys/swap.h>
137 | #include <sys/syscall.h>

<unknown>:0: error: stack nearly exhausted; compilation time may suffer, and crashes due to stack overflow are likely
<unknown>:0: error: could not build C module 'SwiftMusl'
[719/1348] Compiling x_all.cc
make[1]: *** [all] Error 1
make: *** [vminitd] Error 2
```

To update:

- Run `make cross-prep`
- List the installed Static Linux SDKs using `swift sdk list`
- Remove the old Static Linux SDKs using `swift sdk remove <SDK>`

Optionally:

- List the installed toolchains using `swiftly list`
- Uninstalled the old toolchains using `swiftly uninstall <TOOLCHAIN>`
2025-09-11 10:16:31 -07:00
Michael Crosby 753aa080f0 make Import and Export public types (#284)
Signed-off-by: crosbymichael <michael_crosby@apple.com>
2025-09-09 16:29:05 -04:00
Dmitry Kovba 1b1cfdbaf3 Add comments clarifying thread-safety (#282) 2025-09-08 23:15:22 -07:00
Danny Canter 9aa552593b LinuxContainer: Try and stop vm on start failure (#281)
If start fails today the vm stays running.
2025-09-05 11:14:52 -07:00
Dmitry Kovba 9319eecf14 Prevent a leak detection crash when close() fails (#280)
When an image is broken, `container-core-images` may crash with:
```
Application Specific Information:
_NIOFileSystem/SystemFileHandle.swift:131: Fatal error: Leaking file descriptor: the handle for '/Users/Dmitry/Library/Application Support/com.apple.container/content/ingest/03144D38-D98D-4833-9E0C-60229BF653D9/.tmp-MIB1oc' MUST be closed or detached with 'close()' or 'detachUnsafeFileDescriptor()' before the final reference to the handle is dropped.

Thread 9 Crashed:
0   libswiftCore.dylib            	       0x1adbfe110 _assertionFailure(_:_:file:line:flags:) + 176
1   container-core-images         	       0x105773628 closure #1 in SystemFileHandle.deinit + 424 (SystemFileHandle.swift:131)
2   container-core-images         	       0x10577365c partial apply for closure #1 in SystemFileHandle.deinit + 20
3   container-core-images         	       0x104ebd994 closure #1 in LockStorage.withLockedValue<A>(_:) + 124 (NIOLock.swift:183)
4   container-core-images         	       0x104ebde38 partial apply for closure #1 in LockStorage.withLockedValue<A>(_:) + 52
5   container-core-images         	       0x104c387fc ManagedBuffer<>.withUnsafeMutablePointers<A, B>(_:) + 152
6   container-core-images         	       0x104ebd8ec LockStorage.withLockedValue<A>(_:) + 172 (NIOLock.swift:180)
7   container-core-images         	       0x104ebe088 NIOLockedValueBox.withLockedValue<A>(_:) + 104 (NIOLockedValueBox.swift:38)
8   container-core-images         	       0x105773438 SystemFileHandle.deinit + 112 (SystemFileHandle.swift:128)
9   container-core-images         	       0x105773684 SystemFileHandle.__deallocating_deinit + 28
10  libswiftCore.dylib            	       0x1adaeef50 _swift_release_dealloc + 56
11  libswiftCore.dylib            	       0x1adaefabc bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1>>::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) + 152
12  container-core-images         	       0x104b81aac RegistryClient.fetchBlob(name:descriptor:into:progress:) + 180 (RegistryClient+Fetch.swift:200)
13  container-core-images         	       0x104b9f481 protocol witness for ContentClient.fetchBlob(name:descriptor:into:progress:) in conformance RegistryClient + 1
14  container-core-images         	       0x1049b6b29 ImageStore.ImportOperation.fetchBlob(_:) + 1 (ImageStore+Import.swift:167)
15  container-core-images         	       0x1049b5c6d ImageStore.ImportOperation.fetch(_:) + 1 (ImageStore+Import.swift:153)
16  container-core-images         	       0x1049b4f69 closure #1 in closure #1 in ImageStore.ImportOperation.fetchAll(_:) + 1 (ImageStore+Import.swift:126)
17  container-core-images         	       0x1049bb08d partial apply for closure #1 in closure #1 in ImageStore.ImportOperation.fetchAll(_:) + 1
18  libswift_Concurrency.dylib    	       0x2945e05f9 completeTaskWithClosure(swift::AsyncContext*, swift::SwiftError*) + 1
```

Replacing the `SwiftNIO` file handle with the `Foundation` file handle
resolved the crash. However, this led to a worse performance:

```
Debug version:
SwiftNIO: 1:05s
Foundation: 1:18s (1.2 times worse)

Release version:
SwiftNIO: 0:34s
Foundation: 1:00s (1.8 times worse)
```

This PR attempts to prevent the crash without switching back to the
`Foundation` file handle.
2025-09-04 23:07:11 -07:00
Danny Canter b422e036da ContainerizationOS: Rework User type (#279) 2025-09-04 18:16:17 -07:00
Dmitry Kovba 6a31184ea5 Handle warnings as errors (#271)
To handle warnings as errors when building, use `make`. To allow
warnings, use `make WARNINGS_AS_ERRORS=false test`.

Also see https://github.com/apple/container/pull/535.
2025-08-28 10:39:17 -04:00
Eric Ernst f92c0cd8c6 containerization: Add additional tests (#273)
Add additional tests, with varying levels of utility.

Before: Overall Code Coverage: 41.73%
After: Overall Code Coverage: 42.95%

Signed-off-by: Eric Ernst <eric_ernst@apple.com>
2025-08-26 13:13:05 -07:00
Agam Dua 4099bdccd6 vminitd: Removed extraneous import (#276)
We shouldn't need this import anymore

cc: @crosbymichael

Signed-off-by: Agam Dua <agam_dua@apple.com>
2025-08-26 09:36:44 -07:00
Danny Canter df2425ef7f vminitd: Wait for execvpe to return to continue (#275)
Today, because we don't wait for execvpe to finish to continue onwards,
it's possible that if you did an exec quick enough after starting an
init process for a container, that you could join the init processes
namespaces before pivot_root has taken place which is quite fun. Let's
wait for exec to finish (or an error to occur) to prevent this.
2025-08-26 09:34:13 -07:00
Danny Canter 48e2f412b3 vminitd: Log spec for exec processes (#274)
We had a log for the initial oci runtime spec, but we don't log anything
for execed processes. This makes it hard to look into issues that may be
due to just a mistake in the spec and nothing wrong with the actual
logic of the program.
2025-08-25 12:26:35 -07:00
Danny Canter 53021bec36 Cgroup2Manager: Various adjustments (#270)
Systemd loves to move the root cgroups processes to one it created named
/init.scope and then write the root cgs subtree_control file. Because of
this we can't just add exec processes to the cg we made for the
container anymore as we'll get EBUSY. We should follow where the init
processes cg is actually at (/proc/pid/cgroup) and add it there.
2025-08-19 17:31:51 -07:00
Danny Canter 2f32e36a0d Cgroup2Manager: Fix error log mistake (#269)
I accidentally made the creation log error level. Additionally adds a
log to deletion of the cg.
2025-08-18 12:19:55 -04:00
Dmitry Kovba c3f5816353 Handle the same file name in the fetchBlob method (#258)
With the suggested change, when a file exists, we'll verify whether it
has the same content before skipping it.
2025-08-15 14:02:22 -04:00
Michael Crosby 54980872d9 add ability to export initfs as block (#268)
This refactors the rootfs command to produce an image and have the
ability to create an ext4 formatted block of the init filesystem
directly from the command.

closes #220

Signed-off-by: crosbymichael <michael_crosby@apple.com>
2025-08-15 00:12:14 -07:00
Michael Crosby e08b0d4fb4 add kernel support section to readme (#267)
closes #224

Signed-off-by: crosbymichael <michael_crosby@apple.com>
2025-08-14 15:15:43 -07:00
Danny Canter 531ccd6205 vminitd: Rename CgroupManager -> Cgroup2Manager (#266)
To be more explicit.
2025-08-13 20:16:03 -04:00