perf(docker): parallelize multi-arch build and improve layer caching

Split the single docker job into a matrix (amd64/arm64) that builds in
parallel, then merge via docker-manifest job. Also restructure the
Dockerfile to pre-compile dependencies with dummy sources so the dep
layer is cached by GHA when only application code changes.
This commit is contained in:
t8y2
2026-05-06 00:14:05 +08:00
parent a11695b1e5
commit dc9d4e2b9c
2 changed files with 76 additions and 18 deletions
+56 -12
View File
@@ -108,7 +108,7 @@ jobs:
args: --target ${{ matrix.target }}
publish:
needs: [build, docker]
needs: [build, docker-manifest]
runs-on: ubuntu-latest
steps:
- name: Publish draft release
@@ -318,6 +318,10 @@ jobs:
docker:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform: [linux/amd64, linux/arm64]
steps:
- uses: actions/checkout@v4
@@ -333,18 +337,58 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ secrets.DOCKERHUB_USERNAME }}/dbx,push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,scope=${{ matrix.platform }},mode=max
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
docker-manifest:
needs: docker
runs-on: ubuntu-latest
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/dbx:${{ steps.version.outputs.version }}
${{ secrets.DOCKERHUB_USERNAME }}/dbx:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
-t ${{ secrets.DOCKERHUB_USERNAME }}/dbx:${{ steps.version.outputs.version }} \
-t ${{ secrets.DOCKERHUB_USERNAME }}/dbx:latest \
$(printf '${{ secrets.DOCKERHUB_USERNAME }}/dbx@sha256:%s ' *)
+20 -6
View File
@@ -23,17 +23,31 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& rustup target add x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu \
&& rm -rf /var/lib/apt/lists/*
# Copy dependency manifests only and create dummy sources to pre-compile dependencies.
# This layer is cached by GHA as long as Cargo.toml/Cargo.lock don't change.
COPY Cargo.toml Cargo.lock ./
COPY crates/ crates/
COPY src-web/ src-web/
RUN mkdir -p src-tauri/src && echo 'fn main() {}' > src-tauri/src/main.rs && echo 'pub fn run() {}' > src-tauri/src/lib.rs
COPY crates/dbx-core/Cargo.toml crates/dbx-core/
COPY src-web/Cargo.toml src-web/
COPY src-tauri/Cargo.toml src-tauri/
RUN mkdir -p crates/dbx-core/src && echo '' > crates/dbx-core/src/lib.rs \
&& mkdir -p src-web/src && echo 'fn main() {}' > src-web/src/main.rs \
&& mkdir -p src-tauri/src && echo 'fn main() {}' > src-tauri/src/main.rs && echo 'pub fn run() {}' > src-tauri/src/lib.rs
COPY src-tauri/build.rs src-tauri/
COPY src-tauri/tauri.conf.json src-tauri/
RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry-$TARGETARCH \
--mount=type=cache,target=/app/target,id=cargo-target-$TARGETARCH \
case "$TARGETARCH" in \
RUN case "$TARGETARCH" in \
amd64) rust_target=x86_64-unknown-linux-gnu ;; \
arm64) rust_target=aarch64-unknown-linux-gnu ;; \
*) echo "Unsupported TARGETARCH: $TARGETARCH" >&2; exit 1 ;; \
esac && \
cargo zigbuild --release -p dbx-web --target "$rust_target" || true
# Copy real sources and rebuild (only application code recompiles)
COPY crates/ crates/
COPY src-web/ src-web/
RUN case "$TARGETARCH" in \
amd64) rust_target=x86_64-unknown-linux-gnu ;; \
arm64) rust_target=aarch64-unknown-linux-gnu ;; \
*) echo "Unsupported TARGETARCH: $TARGETARCH" >&2; exit 1 ;; \