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>
This commit is contained in:
Eric Ernst
2025-09-19 02:13:54 -07:00
committed by GitHub
parent 898e3ae6be
commit 51ef9f81fe
6 changed files with 384 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
# Copyright © 2025 Apple Inc. and the Containerization project authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ctr-example Makefile
SWIFT = /usr/bin/swift
.PHONY: all build clean run
all: build
build:
$(SWIFT) build --configuration release
codesign --force --sign - --entitlements ctr-example.entitlements ./.build/release/ctr-example
cp ./.build/release/ctr-example ./ctr-example
clean:
$(SWIFT) package clean
rm -f ./ctr-example
run: build
./ctr-example
# Development targets
debug:
$(SWIFT) build
codesign --force --sign - --entitlements ctr-example.entitlements ./.build/debug/ctr-example
fmt:
$(SWIFT) format --in-place --recursive Sources/
+213
View File
@@ -0,0 +1,213 @@
{
"originHash" : "596c757bf0a22a54817d60de250dc349ae2da22ce1dfca2785b16a723baa0e6b",
"pins" : [
{
"identity" : "async-http-client",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swift-server/async-http-client.git",
"state" : {
"revision" : "254d34096123cd5da4f82e69f52f622ac7526d68",
"version" : "1.27.0"
}
},
{
"identity" : "containerization",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/containerization.git",
"state" : {
"revision" : "4099bdccd615bca49a2ea9cdb5b20dc5c5bd0fea",
"version" : "0.6.2"
}
},
{
"identity" : "grpc-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/grpc/grpc-swift.git",
"state" : {
"revision" : "a56a157218877ef3e9625f7e1f7b2cb7e46ead1b",
"version" : "1.26.1"
}
},
{
"identity" : "swift-algorithms",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-algorithms.git",
"state" : {
"revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023",
"version" : "1.2.1"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"state" : {
"revision" : "309a47b2b1d9b5e991f36961c983ecec72275be3",
"version" : "1.6.1"
}
},
{
"identity" : "swift-asn1",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-asn1.git",
"state" : {
"revision" : "f70225981241859eb4aa1a18a75531d26637c8cc",
"version" : "1.4.0"
}
},
{
"identity" : "swift-async-algorithms",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-async-algorithms.git",
"state" : {
"revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b",
"version" : "1.0.4"
}
},
{
"identity" : "swift-atomics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-atomics.git",
"state" : {
"revision" : "b601256eab081c0f92f059e12818ac1d4f178ff7",
"version" : "1.3.0"
}
},
{
"identity" : "swift-certificates",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-certificates.git",
"state" : {
"revision" : "20c451f1ad8e344e61ddbb34ef196653d4b73ea6",
"version" : "1.13.0"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections.git",
"state" : {
"revision" : "8c0c0a8b49e080e54e5e328cc552821ff07cd341",
"version" : "1.2.1"
}
},
{
"identity" : "swift-crypto",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-crypto.git",
"state" : {
"revision" : "d1c6b70f7c5f19fb0b8750cb8dcdf2ea6e2d8c34",
"version" : "3.15.0"
}
},
{
"identity" : "swift-http-structured-headers",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-http-structured-headers.git",
"state" : {
"revision" : "1625f271afb04375bf48737a5572613248d0e7a0",
"version" : "1.4.0"
}
},
{
"identity" : "swift-http-types",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-http-types.git",
"state" : {
"revision" : "a0a57e949a8903563aba4615869310c0ebf14c03",
"version" : "1.4.0"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
"revision" : "ce592ae52f982c847a4efc0dd881cc9eb32d29f2",
"version" : "1.6.4"
}
},
{
"identity" : "swift-nio",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio.git",
"state" : {
"revision" : "1c30f0f2053b654e3d1302492124aa6d242cdba7",
"version" : "2.86.0"
}
},
{
"identity" : "swift-nio-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-extras.git",
"state" : {
"revision" : "a55c3dd3a81d035af8a20ce5718889c0dcab073d",
"version" : "1.29.0"
}
},
{
"identity" : "swift-nio-http2",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-http2.git",
"state" : {
"revision" : "5e9e99ec96c53bc2c18ddd10c1e25a3cd97c55e5",
"version" : "1.38.0"
}
},
{
"identity" : "swift-nio-ssl",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-ssl.git",
"state" : {
"revision" : "737e550e607d82bf15bdfddf158ec61652ce836f",
"version" : "2.34.0"
}
},
{
"identity" : "swift-nio-transport-services",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-transport-services.git",
"state" : {
"revision" : "e645014baea2ec1c2db564410c51a656cf47c923",
"version" : "1.25.1"
}
},
{
"identity" : "swift-numerics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-numerics.git",
"state" : {
"revision" : "bbadd4b853a33fd78c4ae977d17bb2af15eb3f2a",
"version" : "1.1.0"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "e3f69fd321d0c9fcdc16fb576a0cdd956675face",
"version" : "1.31.0"
}
},
{
"identity" : "swift-service-lifecycle",
"kind" : "remoteSourceControl",
"location" : "https://github.com/swift-server/swift-service-lifecycle.git",
"state" : {
"revision" : "e7187309187695115033536e8fc9b2eb87fd956d",
"version" : "2.8.0"
}
},
{
"identity" : "swift-system",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-system.git",
"state" : {
"revision" : "890830fff1a577dc83134890c7984020c5f6b43b",
"version" : "1.6.2"
}
}
],
"version" : 3
}
+45
View File
@@ -0,0 +1,45 @@
// swift-tools-version: 6.2
//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the Containerization project authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
import PackageDescription
let scVersion = "0.6.2"
let package = Package(
name: "ctr-example",
platforms: [
.macOS("26.0")
],
products: [
.executable(
name: "ctr-example",
targets: ["ctr-example"]
)
],
dependencies: [
.package(url: "https://github.com/apple/containerization.git", exact: Version(stringLiteral: scVersion))
],
targets: [
.executableTarget(
name: "ctr-example",
dependencies: [
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
]
)
]
)
+3
View File
@@ -0,0 +1,3 @@
#
Very basic example of launching a Linux container using Containerization.
@@ -0,0 +1,74 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025 Apple Inc. and the Containerization project authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//
import Containerization
import ContainerizationOS
import Foundation
@main
struct CtrExample {
static func main() async throws {
print("Starting container example...")
// Set up terminal in raw mode (like cctl)
let current = try Terminal.current
try current.setraw()
defer { current.tryReset() }
// Create container manager with file-based initfs
var manager = try await ContainerManager(
kernel: Kernel(path: URL(fileURLWithPath: "./vmlinux"), platform: .linuxArm),
initfsReference: "vminit:latest",
network: try ContainerManager.VmnetNetwork()
)
let containerId = "ctr-example"
let imageReference = "docker.io/library/alpine:3.16"
print("Creating container from \(imageReference)...")
// Create container with simple configuration
let container = try await manager.create(
containerId,
reference: imageReference,
rootfsSizeInBytes: 1.gib()
) { @Sendable config in
config.cpus = 2
config.memoryInBytes = 512.mib()
config.process.setTerminalIO(terminal: current)
config.process.arguments = ["/bin/sh"]
config.process.workingDirectory = "/"
}
// Clean up on exit
defer {
try? manager.delete(containerId)
}
print("Starting container...")
try await container.create()
try await container.start()
// Resize terminal to match current window
try? await container.resize(to: try current.size)
// Wait for container to finish
let exitCode = try await container.wait()
print("Container exited with code \(exitCode)")
try await container.stop()
}
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.virtualization</key>
<true/>
</dict>
</plist>