为什么 Swift 和 Docker 是服务器开发的理想组合
\n\n如果您习惯认为 Swift 只用于 iOS 移动开发,那么是时候改变看法了。Swift 正自信地迈向服务器端:Vapor、Kitura、Perfect 等框架让您可以编写快速且安全的后端程序。但有一个问题:如何确保您的应用程序在开发者的 Mac 和生产环境的 Ubuntu 服务器上运行一致?
\n\n答案就是——使用 Docker 容器化 Swift 应用。Docker 可以打包所有内容:可执行文件本身、系统库、Swift Package Manager (SPM) 依赖项——并且可以在任何地方运行。再也不会有“在我这能运行”和“在我这不行”的问题。
\n\n在本文中,我们将介绍如何将 Swift 应用程序构建到 Docker 镜像中,优化其大小,配置多阶段构建,甚至为开发添加热重载功能。开始吧!
\n\n步骤 1. 准备 Swift 应用程序
\n\n作为示例,我们将使用一个基于 Vapor 的最小 Web 应用程序。如果您还没有项目,请创建一个:
\n\nmkdir MySwiftApp && cd MySwiftApp\nswift package init --type executable\n\n将 Vapor 添加到 Package.swift:
// swift-tools-version:5.7\nimport PackageDescription\n\nlet package = Package(\n name: "MySwiftApp",\n dependencies: [\n .package(url: "https://github.com/vapor/vapor.git", from: "4.89.0")\n ],\n targets: [\n .executableTarget(\n name: "MySwiftApp",\n dependencies: [\n .product(name: "Vapor", package: "vapor")\n ]\n )\n ]\n)\n\n最简单的 main.swift:
\n\nimport Vapor\n\nvar env = try Environment.detect()\ntry LoggingSystem.bootstrap(from: &env)\nlet app = Application(env)\ndefer { app.shutdown() }\n\napp.get("hello") { req -> String in\n return "Hello from Swift in Docker!"\n}\n\ntry app.run()\n\n检查项目是否可以在本地编译:swift build。如果一切正常,我们进入容器化步骤。
步骤 2. 为 Swift 编写 Dockerfile
\n\n良好 Swift 容器化的主要秘诀是——多阶段构建。第一阶段,我们编译可执行文件;第二阶段,只复制可执行文件和运行时依赖项。最终镜像大小会缩小 5-10 倍。
\n\n# ---- 阶段 1:构建 ----\nFROM swift:5.9-jammy AS build\n\nWORKDIR /app\n\n# 复制 Package.swift 和 Package.resolved 以缓存依赖项\nCOPY Package.swift ./\nCOPY Package.resolved ./\n\n# 单独下载依赖项——这会被 Docker 缓存\nRUN swift package resolve\n\n# 复制源代码\nCOPY Sources ./Sources\n\n# 以 release 模式构建\nRUN swift build -c release --static-swift-stdlib\n\n# ---- 阶段 2:运行时 ----\nFROM ubuntu:jammy AS runtime\n\n# 安装 Swift 运行时所需的最小依赖项\nRUN apt-get update && apt-get install -y \\\n libicu70 \\\n libcurl4 \\\n libxml2 \\\n && rm -rf /var/lib/apt/lists/*\n\nWORKDIR /app\n\n# 仅从构建阶段复制可执行文件\nCOPY --from=build /app/.build/release/MySwiftApp .\n\n# Vapor 默认监听的端口\nEXPOSE 8080\n\nCMD ["./MySwiftApp"]\n\n关键点:
\n- \n
--static-swift-stdlib— 静态链接标准库,避免在运行时携带 libswiftCore.so。 \n - 分离 COPY 操作——先复制
Package.swift,再复制代码。这样 Docker 可以利用层缓存,在修改源代码时不会重新构建依赖项。 \n - 基础镜像
ubuntu:jammy大小约为 80 MB,最终镜像大小约为 100-150 MB。 \n
步骤 3. 构建并运行容器
\n\n构建镜像:
\n\ndocker build -t my-swift-app .\n\n运行:
\n\ndocker run -p 8080:8080 my-swift-app\n\nO