Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Add the plugin to your project

Make Swift Container Plugin available in your project

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)
```
28 changes: 28 additions & 0 deletions Sources/swift-container-plugin/Documentation.docc/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?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">
<!--
This source file is part of the Swift.org open source project

Copyright (c) 2024 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
-->
<plist version="1.0">
<dict>
<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,5 @@
# Installing dependencies

* 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.
* A container runtime is not required to build an image, but one must be available wherever the image is to be run.
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.
41 changes: 41 additions & 0 deletions Sources/swift-container-plugin/Documentation.docc/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 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

* 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
```
20 changes: 20 additions & 0 deletions Sources/swift-container-plugin/Documentation.docc/run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Run your service

## Overview

Swift Container Plugin builds standards-compliant container images which can run in public or private cloud infrastructure, or locally on a desktop container runtime.

The following command uses `podman` to run the service locally, making it available on port 8080:

```
% 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
```

When the service has started, we can access it with a web browser or `curl`:
```
% curl localhost:8080
Hello World, from Hummingbird on Ubuntu 24.04.2 LTS
```
19 changes: 19 additions & 0 deletions Sources/swift-container-plugin/Empty.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftContainerPlugin open source project
//
// Copyright (c) 2024 Apple Inc. and the SwiftContainerPlugin project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftContainerPlugin project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// This is an empty source file used to make SwiftContainerPluginDocumentation a valid
// documentation build target.

// SwiftContainerPluginDocumentation is an otherwise empty target that includes high-level,
// user-facing documentation about using the Swift Container Plugin from the command-line.
6 changes: 6 additions & 0 deletions Sources/swift-container-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# ContainerImageBuilder Plugin Documentation

`ContainerImageBuilderPluginDocumentation` is an otherwise empty target that includes high-level,
user-facing documentation about using the ContainerImageBuilder plugin from the command-line.

<!-- Copyright (c) 2024 Apple Inc and the Swift Project authors. All Rights Reserved. -->