-
Notifications
You must be signed in to change notification settings - Fork 1
Server guide packaging #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
heckj
wants to merge
12
commits into
swiftlang:main
Choose a base branch
from
heckj:server-guide-packaging
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
9631793
initial copy from website content - documentation/server/guides/packa…
heckj 0513719
rework overview
heckj f68e805
Enhance packaging.md with container and build details
heckj d07abb7
setup
heckj 8c6bd71
swift images, ref to org base images
heckj 552b9d7
more sections
heckj 78b2dac
more packaging
heckj 7ded4ab
grammar and style fixes
heckj 9630aa9
more fixes
heckj 46338e4
split up some of the longer sentences
heckj 546dc7d
pre-fixes
heckj 8af5fae
more grammar fixes, tightening wording
heckj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,6 @@ | ||
| # ``ServerGuides`` | ||
|
|
||
| ## Topics | ||
|
|
||
| - <doc:packaging> | ||
| - <doc:deploying-static-binaries> |
173 changes: 173 additions & 0 deletions
173
server-guides/Sources/ServerGuides.docc/deploying-static-binaries.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| # Deploying Swift services as static binaries | ||
|
|
||
| Build fully self-contained Swift executables and deploy them | ||
| to minimal containers or directly to Linux machines. | ||
|
|
||
| ## Overview | ||
|
|
||
| The Static Linux SDK produces Swift executables with no external dependencies — | ||
| not even the C library. | ||
| This lets you run the binary on any Linux machine regardless of distribution, | ||
| which opens deployment options that aren't possible with dynamically linked builds. | ||
|
|
||
| You can copy the binary into a `scratch` or distroless container image that contains nothing but your executable. | ||
| Or skip containers entirely and copy the binary to a virtual machine. | ||
| Either way, the result is the smallest possible deployment artifact with the smallest possible attack surface. | ||
|
|
||
| This article walks you through installing the SDK, building a static binary, and deploying it. | ||
|
|
||
| ### Install the Static Linux SDK | ||
|
|
||
| The Static Linux SDK requires an open source Swift toolchain. | ||
| The toolchain bundled with Xcode doesn't support SDK-based cross-compilation. | ||
| Use `swiftly` to install an open source Swift toolchain, then install the Static Linux SDK for that toolchain. | ||
| Go to [swift.org](https://www.swift.org/install/) for the links and commands to install both. | ||
|
|
||
| Install the SDK with `swift sdk install`, providing the URL for your Swift version. | ||
| The command follows this form: | ||
|
|
||
| ```bash | ||
| swift sdk install <url> --checksum <checksum> | ||
| ``` | ||
|
|
||
| After installation, verify the SDK is available: | ||
|
|
||
| ```bash | ||
| swift sdk list | ||
| ``` | ||
|
|
||
| The output includes SDK names like `x86_64-swift-linux-musl` | ||
| and `aarch64-swift-linux-musl` that you use in build commands. | ||
|
|
||
| ### Build a static binary | ||
|
|
||
| Build your service with the `--swift-sdk` flag, | ||
| specifying the target architecture: | ||
|
|
||
| ```bash | ||
| swift build -c release --swift-sdk aarch64-swift-linux-musl | ||
| ``` | ||
|
|
||
| For x86_64 targets, use the corresponding SDK name: | ||
|
|
||
| ```bash | ||
| swift build -c release --swift-sdk x86_64-swift-linux-musl | ||
| ``` | ||
|
|
||
| This produces a statically linked ELF binary in `.build/release/` | ||
| that you can copy to any Linux system and run directly. | ||
| The SDK uses [Musl](https://musl.libc.org) instead of Glibc | ||
| and statically links everything the executable needs — | ||
| including the Swift standard library, Foundation, and system libraries | ||
| like libcurl and libxml2. | ||
|
|
||
| > Note: Because Musl replaces Glibc, | ||
| > some packages that import C libraries need changes — | ||
| > for example, changing import lines from `Glibc` to `Musl`. | ||
| > The Swift standard library and Foundation handle this automatically. | ||
|
|
||
| ### Deploy to a distroless container image | ||
|
|
||
| A distroless container image contains no operating system utilities — | ||
| no package manager, no shell, nothing but what you put in it. | ||
| This eliminates an entire class of potential vulnerabilities | ||
| because there are no extra programs an attacker could exploit. | ||
|
|
||
| Because the Static Linux SDK cross-compiles from your development machine, | ||
| you don't need a multi-stage Dockerfile with a Swift SDK builder image. | ||
| Build the binary locally, then use a minimal `Dockerfile` | ||
| that copies the pre-built executable into a `scratch` image — | ||
| a completely empty base image: | ||
|
|
||
| ```bash | ||
| swift build -c release --swift-sdk aarch64-swift-linux-musl | ||
| ``` | ||
|
|
||
| ```Dockerfile | ||
| FROM scratch | ||
| COPY .build/release/<executable-name> / | ||
|
|
||
| EXPOSE 8080 | ||
| ENTRYPOINT ["/<executable-name>"] | ||
| ``` | ||
|
|
||
| The final image contains a single file: your executable. | ||
|
|
||
| If your service makes outbound TLS connections, | ||
| the image also needs CA certificates. | ||
| Copy them from any Linux image at build time: | ||
|
|
||
| ```Dockerfile | ||
| FROM ubuntu:noble AS certs | ||
| RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates | ||
|
|
||
| FROM scratch | ||
| COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ | ||
| COPY .build/release/<executable-name> / | ||
|
|
||
| EXPOSE 8080 | ||
| ENTRYPOINT ["/<executable-name>"] | ||
| ``` | ||
|
|
||
| Build the container image: | ||
|
|
||
| ```bash | ||
| container build -t <my-app>:latest . | ||
| ``` | ||
|
|
||
| > Note: A `scratch`-based image doesn't include a shell, | ||
| > so you can't use `container run --rm -it <my-app> /bin/sh` to debug. | ||
| > If you need a shell for troubleshooting, | ||
| > use a slim base image during development and switch to `scratch` for production. | ||
|
|
||
| ### Build and publish with Swift Container Plugin | ||
|
|
||
| The [Swift Container Plugin](https://github.com/apple/swift-container-plugin) | ||
| combines building, packaging, and pushing to a registry into a single command. | ||
| It builds your service with the Static Linux SDK, | ||
| packages the executable into a container image, | ||
| and publishes the image to a container registry — all without a Dockerfile. | ||
|
|
||
| Add the plugin to your `Package.swift`: | ||
|
|
||
| ```swift | ||
| dependencies: [ | ||
| .package(url: "https://github.com/apple/swift-container-plugin", from: "0.1.0"), | ||
| ], | ||
| ``` | ||
|
|
||
| Then build and publish: | ||
|
|
||
| ```bash | ||
| swift package --swift-sdk aarch64-swift-linux-musl \ | ||
| build-container-image --repository registry.example.com/my-app | ||
| ``` | ||
|
|
||
| The plugin produces a minimal image equivalent to one from a `scratch`-based Dockerfile | ||
| and pushes it to the specified registry. | ||
| Run the published image with any container runtime: | ||
|
|
||
| ```bash | ||
| container run -p 8080:8080 registry.example.com/my-app | ||
| ``` | ||
|
|
||
| > Tip: The container plugin is especially useful in CI pipelines | ||
| > where you want a single, repeatable command | ||
| > that produces a ready-to-deploy image. | ||
|
|
||
| ### Deploy directly to a Linux machine | ||
|
|
||
| A static binary runs on any Linux machine, so you can copy it directly to a virtual machine or bare-metal server: | ||
|
|
||
| ```bash | ||
| scp .build/release/<executable-name> user@server:/usr/local/bin/ | ||
| ``` | ||
|
|
||
| On the server, run the executable directly: | ||
|
|
||
| ```bash | ||
| ssh user@server /usr/local/bin/<executable-name> | ||
| ``` | ||
|
|
||
| Use your preferred configuration management tool, such as Ansible, Chef, Puppet, or shell scripts, | ||
| to automate deployment across multiple hosts. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So overall this tutorial looks great but I'm not sure we want to make this server specific? CLI tools especially work great with the static SDK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see where you're going, however I'm not sure how we'd broadly like to reconcile initial goals of porting and updating the swift server guides into DocC and getting them published, specific to the server side use cases. I totally agree it's a fantastic possible mechanism to make easily-used executables that can run on linux or macOS (or other platforms, as long as they can run a Linux container).
I've got queued up to move the "getting started with Static Linux SDK" as it's own article - and it sounds like "Swift on Linux" is a worthwhile thing, @FranzBusch has made the same comments to me. So let me ask - does this article sound like it's wrong or doesn't fit here, because it's more aligned elsewhere or with something else, or are you thinking that we just need a broader scope for content that is "Swift on Linux" more generally?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, general guides for building Swift applications and another guide for building docker images makes sense. Neither of those should be tied to the Swift Server use-case since they are generally useful to many different use-cases.