应用程序部署打包
一旦应用程序构建完成并准备用于生产环境,它仍然需要进行打包才能部署到服务器。有几种策略可以用于打包 Swift 应用程序以进行部署。
Docker
如今,打包应用程序最流行的方式之一是使用容器技术,例如 Docker。
使用 Docker 的工具,我们可以构建应用程序并将其打包为 Docker 镜像,发布到 Docker 仓库,然后直接在服务器上或在支持 Docker 部署的平台(如 Kubernetes)上启动它。许多公共云提供商,包括 AWS、GCP、Azure、IBM 等,都鼓励这种部署方式。
这是一个示例 Dockerfile
,它在 CentOS 之上构建和打包应用程序
#------- build -------
FROM swift:centos8 as builder
# set up the workspace
RUN mkdir /workspace
WORKDIR /workspace
# copy the source to the docker image
COPY . /workspace
RUN swift build -c release --static-swift-stdlib
#------- package -------
FROM centos
# copy executables
COPY --from=builder /workspace/.build/release/<executable-name> /
# set the entry point (application name)
CMD ["<executable-name>"]
要从 Dockerfile
创建本地 Docker 镜像,请从应用程序的源代码位置使用 docker build
命令,例如:
$ docker build . -t <my-app>:<my-app-version>
要测试本地镜像,请使用 docker run
命令,例如:
$ docker run <my-app>:<my-app-version>
最后,使用 docker push
命令将应用程序的 Docker 镜像发布到您选择的 Docker 仓库,例如:
$ docker tag <my-app>:<my-app-version> <docker-hub-user>/<my-app>:<my-app-version>
$ docker push <docker-hub-user>/<my-app>:<my-app-version>
此时,应用程序的 Docker 镜像已准备好部署到服务器主机(需要运行 Docker)或支持 Docker 部署的平台之一。
有关 Docker 的更完整信息,请参阅 Docker 文档。
Distroless
Distroless 是 Google 的一个项目,旨在创建最小化的镜像,其中仅包含应用程序及其运行时依赖项。它们不包含包管理器、shell 或您期望在标准 Linux 发行版中找到的任何其他程序。
由于 Distroless 支持 Docker 并且基于 Debian,因此在其上打包 Swift 应用程序与上面的 Docker 过程非常相似。这是一个示例 Dockerfile
,它在 Distroless 的 C++ 基础镜像之上构建和打包应用程序
#------- build -------
# Building using Ubuntu Bionic since its compatible with Debian runtime
FROM swift:bionic as builder
# set up the workspace
RUN mkdir /workspace
WORKDIR /workspace
# copy the source to the docker image
COPY . /workspace
RUN swift build -c release --static-swift-stdlib
#------- package -------
# Running on distroless C++ since it includes
# all(*) the runtime dependencies Swift programs need
FROM gcr.io/distroless/cc-debian10
# copy executables
COPY --from=builder /workspace/.build/release/<executable-name> /
# set the entry point (application name)
CMD ["<executable-name>"]
请注意,上面使用了 gcr.io/distroless/cc-debian10
作为运行时镜像,这应该适用于不使用 FoundationNetworking
或 FoundationXML
的 Swift 程序。为了提供更完整的支持,我们(社区)可以向 Distroless 提交 PR,以引入一个 Swift 基础镜像,其中包含 libcurl
和 libxml
,它们分别是 FoundationNetworking
和 FoundationXML
所必需的。
归档文件(Tarball、ZIP 文件等)
由于 Mac 或 Windows 上尚不支持为 Linux 进行 Swift 交叉编译,我们需要使用 Docker 等虚拟化技术来编译目标在 Linux 上运行的应用程序。
也就是说,这并不意味着我们必须将应用程序打包为 Docker 镜像才能部署它们。虽然使用 Docker 镜像进行部署既方便又流行,但应用程序也可以使用简单轻量级的归档格式(如 tarball 或 ZIP 文件)进行打包,然后上传到服务器,在那里可以解压并运行。
这是一个使用 Docker 和 tar
构建和打包应用程序以部署在 Ubuntu 服务器上的示例
首先,从应用程序的源代码位置使用 docker run
命令来构建它
$ docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
swift:bionic \
/bin/bash -cl "swift build -c release --static-swift-stdlib"
请注意,我们正在绑定挂载源代码目录,以便构建将构建产物写入本地驱动器,稍后我们将从中打包它们。
接下来,我们可以创建一个包含应用程序可执行文件的暂存区
$ docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
swift:bionic \
/bin/bash -cl ' \
rm -rf .build/install && mkdir -p .build/install && \
cp -P .build/release/<executable-name> .build/install/'
请注意,此命令可以与上面的构建命令结合使用——我们将其分开是为了使示例更具可读性。
最后,从暂存目录创建一个 tarball
$ tar cvzf <my-app>-<my-app-version>.tar.gz -C .build/install .
我们可以通过将其解压缩到目录并在 Docker 运行时容器中运行应用程序来测试 tarball 的完整性
$ cd <extracted directory>
$ docker run -v "$PWD:/app" -w /app bionic ./<executable-name>
可以将应用程序的 tarball 部署到目标服务器,可以使用诸如 scp
之类的实用程序,或者在更复杂的设置中使用配置管理系统,如 chef
、puppet
、ansible
等。
源代码分发
另一种在 Ruby 或 Javascript 等动态语言中流行的分发技术是将源代码分发到服务器,然后在服务器本身上编译它。
要在服务器上直接构建 Swift 应用程序,服务器必须安装正确的 Swift 工具链。 发布了适用于各种 Linux 发行版的工具链,请确保使用与您的服务器 Linux 版本和所需的 Swift 版本匹配的工具链。
这种方法的主要优点是它很简单。另一个优点是服务器具有完整的工具链(例如调试器),可以帮助在服务器上“实时”排除问题。
这种方法的主要缺点是服务器具有完整的工具链(例如编译器),这意味着复杂的攻击者可能会找到执行代码的方法。他们还可能获得对源代码的访问权限,这些源代码可能是敏感的。如果应用程序代码需要从私有或受保护的仓库克隆,则服务器需要访问凭据,这会增加额外的攻击面。
在大多数情况下,由于这些安全问题,不建议使用源代码分发。
静态链接和 Curl/XML
注意: 如果您使用 -static-stdlib
进行编译,并且将 Curl 与 FoundationNetworking 或 XML 与 FoundationXML 一起使用,则目标系统上必须安装 libcurl 和/或 libxml2 才能使其工作。