切換選單
切換偏好設定選單
切換個人選單
尚未登入
若您做出任何編輯,會公開您的 IP 位址。

在 Ubuntu VPS 上快速編譯 Swift Vapor Project

出自md5.pw
於 2026年4月15日 (三) 15:11 由 Liam留言 | 貢獻 所做的修訂
(差異) ←上個修訂 | 最新修訂 (差異) | 下個修訂→ (差異)

前置說明:

正常情況下,使用 Docker 編譯 Vapor 項目,Swift 的編譯緩存是無法使用的,也就是說每次編譯 Vapor 項目都需要在 Docker 中將 swift-package、whole compile 全走一遍,我的雲服務器在未優化流程之前,每次可能需要耗費十分鐘以上。

測試編譯的機器配置:

Ubuntu 24.04, 2GB RAM, 2 vCPU

原理

Vapor 提供的 Dockerfile 文件是將項目的編譯、複製等操作都放到了 Docker 容器中進行,而 Docker 容器無法緩存編譯信息(意思是下次編譯時無法獲取到上次的編譯緩存進行增量編譯),所以每次都會全量一遍。

而 Vapor 運行,只需要編譯後的 Run 產物和一些必要的 Public、Resource 資源。

依照這個思路,我們可以將 Vapor 的編譯放置到機器上進行,編譯完成後,將 Run 和 Public、Resource 資源拷貝進 Docker 中即可。

安裝 Swift 可參考: 在搬瓦工VPS上安裝 Swift 和他的依賴

該安裝方式與 Swift Docker 保持一致,我正在使用該方式。

更多披露

在 Vapor 項目中新建一個 fastDockerfile, 內容如下:

因為是在機器上編譯,所以這裡只需要使用 -noble/-slim 最小的鏡像進行打包即可

# ================================
# Copy Resources Image
# ================================
FROM ubuntu:24.04 AS build

# Set up a build area
WORKDIR /build

# Copy entire repo into container
COPY . .

# Switch to the staging area
WORKDIR /staging

# Copy main executable to staging area
COPY ./Run ./

# Copy any resources from the public directory and views directory if the directories exist
# Ensure that by default, neither the directory nor any of its contents are writable.
RUN [ -d /build/Public ] && { mv /build/Public ./Public && chmod -R a-w ./Public; } || true
RUN [ -d /build/Resources ] && { mv /build/Resources ./Resources && chmod -R a-w ./Resources; } || true

# ================================
# Run image
# ================================
FROM swift:6.2.1-focal-slim

# Create a vapor user and group with /app as its home directory
RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app vapor

# Switch to the new home directory
WORKDIR /app

# Copy built executable and any staged resources from builder
COPY --from=build --chown=vapor:vapor /staging /app

# Ensure all further commands run as the vapor user
USER vapor:vapor

# Let Docker bind to port 8080
EXPOSE 8080

# Set Language Encoding
ENV LANG C.UTF-8
ENV LC_ALL C.UTF-8

# Start the Vapor service when the image is run, default to listening on 8080 in production environment
ENTRYPOINT ["./Run"]
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]

編寫腳本 fast_build.sh:

請注意,調用腳本時需要提供鏡像名稱

#!/bin/bash

local IMAGE_NAME=${1:-"custom-image:latest"}

echo "🚀 fast building start"

# stop when happen error
set -e

echo "🚀 > git pull"
git pull

echo "🚀 > git submodule update --remote"
git submodule update --remote

echo "🚀 > swift build"
swift build -c release

# move run to .
echo "🚀 > copy {Run} to ./Run"
cp .build/x86_64-unknown-linux-gnu/release/Run ./Run

echo "🚀 > docker build"
docker build -f fastDockerfile . -t $IMAGE_NAME

echo "🚀 > rm local ./Run"
rm -rf ./Run

# redirect
echo "🚀 > sh redirect.main.sh"
docker-compose -f docker-compose.yml up -d

# force clean <none> docker images
echo "🚀 > clean invalid images"
docker image rm -f $(docker images -f dangling=true -q)

echo "🚀 > 🎉🎉🎉 all of done ~"

🎉 OK

驗證

驗證工作,在服務器上快速編譯時,使用

bash fast_build.sh <镜像名称>

例如:

bash fast_build.sh my-image:latest

該腳本將使用上次編譯的緩存(因為是在機器上編譯,而 Dockerfile 只是將機器上編譯完成的產物打包成鏡像),因此將增量編譯時間縮短至 1 分鐘以內,極小的改動僅需 3~8 秒即可完成。