Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .spi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ builder:
configs:
- documentation_targets:
- containertool
- ContainerImageBuilderPlugin
- swift-container-plugin
8 changes: 4 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ let package = Package(
.package(url: "https://github.com/apple/swift-crypto.git", "1.0.0"..<"4.0.0"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.0"),
.package(url: "https://github.com/apple/swift-http-types.git", from: "1.2.0"),
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.0.0"),
],
targets: [
.target(
Expand Down Expand Up @@ -78,12 +78,12 @@ let package = Package(
),
dependencies: [.target(name: "containertool")]
),
// Empty target that builds the DocC catalog at /ContainerImageBuilderPluginDocumentation/ContainerImageBuilder.docc.
// Empty target that builds the DocC catalog at /SwiftContainerPluginDocumentation/Documentation.docc.
// The ContainerImageBuilder catalog includes high-level, user-facing documentation about using
// the ContainerImageBuilder plugin from the command-line.
.target(
name: "ContainerImageBuilderPlugin",
path: "Sources/ContainerImageBuilderPluginDocumentation",
name: "swift-container-plugin",
//path: "Sources/SwiftContainerPluginDocumentation",
exclude: ["README.md"]
),
.testTarget(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Add the plugin to your project

Make Swift Container Plugin available in your project

## Overview

Swift Container Plugin is distributed as a Swift Package Manager package. To make it available, you must add it as a dependency of your project.

### Install the plugin using the `swift package` CLI

Recent versions of `swift package` suupport the `add-dependency` command:

```shell
swift package add-dependency https://github.com/apple/swift-container-plugin --from 0.5.0
```

### Install the plugin by manually editing `Package.swift`

If you cannot use the `swift package add-dependency` comand, append the following lines to your project's `Package.swift` file:

```swift
package.dependencies += [
.package(url: "https://github.com/apple/swift-container-plugin", from: "0.5.0"),
]
```

### Check that the plugin is available

After installation, Swift Package Manager should show that the `ContainerImageBuilder` is now available:

```shell
% swift package plugin --list
‘build-container-image’ (plugin ‘ContainerImageBuilder’ in package ‘swift-container-plugin)
```
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@
-->
<plist version="1.0">
<dict>
<key>CDDefaultCodeListingLanguage</key>
<string>shell</string>
<key>CDDefaultModuleKind</key>
<string>Command Plugin</string>
<key>CDDefaultCodeListingLanguage</key>
<string>shell</string>
<key>CFBundleName</key>
<string>swift-container-plugin</string>
<key>CFBundleDisplayName</key>
<string>swift-container-plugin</string>
<key>CFBundleIdentifier</key>
<string>com.apple.ContainerPlugin</string>
<key>CFBundlePackageType</key>
<string>DOCS</string>
<key>CDDefaultModuleKind</key>
<string>Tool</string>
</dict>
</plist>

Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Swift Container Plugin

@Metadata {
@TechnologyRoot()
}

Build and publish container images using Swift Package Manager.

## Overview

Container images are the standard way to package cloud software today. Once you have packaged your server in a container image, you can deploy it on any container-based public or private cloud service, or run it locally using a desktop container runtime.

Swift Container Plugin makes it easy to build container images for servers written in Swift, using Swift Package Manager.

Find out more and see it in action:

* [How to put Swift in a box](https://fosdem.org/2025/schedule/event/fosdem-2025-5116-how-to-put-swift-in-a-box-building-container-images-with-swift-container-plugin/) at [FOSDEM 2025](https://fosdem.org/2025/schedule/track/swift/).
* [Swift to the cloud in a single step](https://www.youtube.com/watch?v=9AaINsCfZzw) at [ServerSide.Swift 2024](https://www.serversideswift.info/speakers/euan-harris/).

## Usage

Swift Container Plugin can package any executable product defined in `Package.swift` in a container image and publish it to a container registry.

### Build and publish a container image

After adding the plugin to your project, you can build and publish a container image in one step:

```
% swift package --swift-sdk x86_64-swift-linux-musl \
build-container-image --repository registry.example.com/myservice
...
Plugin ‘ContainerImageBuilder’ wants permission to allow all network connections on all ports.
Stated reason: “This command publishes images to container registries over the network”.
Allow this plugin to allow all network connections on all ports? (yes/no) yes
...
Building for debugging...
Build of product 'containertool' complete! (4.95s)
...
Build of product 'hello-world' complete! (5.51s)
...
[ContainerImageBuilder] Found base image manifest: sha256:7bd643386c6e65cbf52f6e2c480b7a76bce8102b562d33ad2aff7c81b7169a42
[ContainerImageBuilder] Found base image configuration: sha256:b904a448fde1f8088913d7ad5121c59645b422e6f94c13d922107f027fb7a5b4
[ContainerImageBuilder] Built application layer
[ContainerImageBuilder] Uploading application layer
[ContainerImageBuilder] Layer sha256:dafa2b0c44d2cfb0be6721f079092ddf15dc8bc537fb07fe7c3264c15cb2e8e6: already exists
[ContainerImageBuilder] Layer sha256:2565d8e736345fc7ba44f9b3900c5c20eda761eee01e01841ac7b494f9db5cf6: already exists
[ContainerImageBuilder] Layer sha256:2c179bb2e4fe6a3b8445fbeb0ce5351cf24817cb0b068c75a219b12434c54a58: already exists
registry.example.com/myservice@sha256:a3f75d0932d052dd9d448a1c9040b16f9f2c2ed9190317147dee95a218faf1df
```

### Run the image

You can deploy your service in the cloud, or use a standards-compliant container runtime such as `podman` to run it locally:

```
% podman run -p 8080:8080 registry.example.com/myservice@sha256:a3f75d0932d052dd9d448a1c9040b16f9f2c2ed9190317147dee95a218faf1df
Trying to pull registry.example.com/myservice@sha256:a3f75d0932d052dd9d448a1c9040b16f9f2c2ed9190317147dee95a218faf1df...
...
2024-05-26T22:57:50+0000 info HummingBird : [HummingbirdCore] Server started and listening on 0.0.0.0:8080
```

Take a look at the [Examples](Examples).

## Topics

### Essentials
- <doc:requirements>
- <doc:Adding-the-plugin-to-your-project>
- <doc:authentication>

### Building and running
- <doc:build>
- <doc:run>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Set up your registry credentials

Configure Swift Container Plugin to authenticate to your container registry

## Overview

Many registries require authentication in order to push images, or even pull them. The plugin can read your registry credentials from a `.netrc` file in your home directory. You can add a netrc record for each registry you need to use, and the plugin will choose the correct one:

```
machine registry.example.com
login myuser
password mypassword
```
42 changes: 42 additions & 0 deletions Sources/swift-container-plugin/Documentation.docc/build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Build and package your service

## Overview

`build-container-image` is a command plugin which takes care of building your service, packaging it in a container image and uploading it to a container registry, all in one command:

```shell
% swift package --swift-sdk x86_64-swift-linux-musl \
build-container-image --from swift:slim --repository registry.example.com/myservice
```

* The `--swift-sdk` argument specifies the Swift SDK with which to build the executable. In this case we are using the Static Linux SDK, which was installed earlier, to build an statically-linked x86_64 Linux binary
* The `--from` argument specifies the base image on which our service will run. `swift:slim` is the default, but you can choose your own base image or use `scratch` if your service does not require a base image at all.
* The `--repository` argument specifies where the plugin will upload our finished image.

The plugin needs permission to connect to the network to publish the image to the registry:

```
Plugin ‘ContainerImageBuilder’ wants permission to allow all network connections on all ports.
Stated reason: “This command publishes images to container registries over the network”.
Allow this plugin to allow all network connections on all ports? (yes/no)
```

Type `yes` to continue.

```
Building for debugging...
Build of product 'containertool' complete! (4.95s)
...
Build of product 'hello-world' complete! (5.51s)
...
[ContainerImageBuilder] Found base image manifest: sha256:7bd643386c6e65cbf52f6e2c480b7a76bce8102b562d33ad2aff7c81b7169a42
[ContainerImageBuilder] Found base image configuration: sha256:b904a448fde1f8088913d7ad5121c59645b422e6f94c13d922107f027fb7a5b4
[ContainerImageBuilder] Built application layer
[ContainerImageBuilder] Uploading application layer
[ContainerImageBuilder] Layer sha256:dafa2b0c44d2cfb0be6721f079092ddf15dc8bc537fb07fe7c3264c15cb2e8e6: already exists
[ContainerImageBuilder] Layer sha256:2565d8e736345fc7ba44f9b3900c5c20eda761eee01e01841ac7b494f9db5cf6: already exists
[ContainerImageBuilder] Layer sha256:2c179bb2e4fe6a3b8445fbeb0ce5351cf24817cb0b068c75a219b12434c54a58: already exists
registry.example.com/myservice@sha256:a3f75d0932d052dd9d448a1c9040b16f9f2c2ed9190317147dee95a218faf1df
```

When it finishes, the plugin prints a reference identifying the new image. Any standard container runtime can use the reference to pull and run your service.
43 changes: 43 additions & 0 deletions Sources/swift-container-plugin/Documentation.docc/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Install a toolchain for cross-compilation (macOS)

The open source Swift toolchain and a compatible Swift SDK make it possible to build Linux executables on macOS

## Overview

* Swift Container Plugin runs on macOS and Linux and requires Swift 6.0 or later.
* On macOS you must install a cross-compilation Swift SDK, such as the [Swift Static Linux SDK](https://www.swift.org/documentation/articles/static-linux-getting-started.html), in order to build executables which can run on Linux-based cloud infrastructure.
* The Swift Static Linux SDK requires the [open source Swift toolchain](https://www.swift.org/install/macos/) to be installed.
* A container runtime is not required to build an image, but you will need one wherever you want to run the image.

### Install the open source Swift toolchain

Follow the instructions at [https://www.swift.org/install/macos/](https://www.swift.org/install/macos/) to install the open source Swift toolchain. The easiest way to do this is to use the [Swiftly swift toolchain installer](https://www.swift.org/install/macos/swiftly/).

### Install a Swift SDK for cross-compilation

If you are running on macOS, you can use a [Swift SDK](https://github.com/apple/swift-evolution/blob/main/proposals/0387-cross-compilation-destinations.md) to cross-compile your server executable for Linux. Either:

* Install the [Static Linux SDK from swift.org](https://www.swift.org/documentation/articles/static-linux-getting-started.html)
* Use [Swift SDK Generator](https://github.com/apple/swift-sdk-generator) to build and install a custom SDK

Let's install the Swift Static Linux SDK:
```
% swift sdk install https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz --checksum 111c6f7d280a651208b8c74c0521dd99365d785c1976a6e23162f55f65379ac6
Downloading a Swift SDK bundle archive from `https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz`...
Downloading
100% [=============================================================]
Downloading swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz

Swift SDK bundle archive successfully downloaded from `https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz`.
Verifying if checksum of the downloaded archive is valid...
Downloaded archive has a valid checksum.
Swift SDK bundle at `https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz` is assumed to be an archive, unpacking...
Swift SDK bundle at `https://download.swift.org/swift-6.1-release/static-sdk/swift-6.1-RELEASE/swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz` successfully installed as swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.
```

Check that the new Swift SDK is now available:

```shell
% swift sdk list
swift-6.1-RELEASE_static-linux-0.0.1
```
Loading