使用 docker 构建 Rust 项目在 google 云上极其缓慢
Building a rust project with docker is extremely slow on google cloud
我对 Rust 比较陌生,但我一直在 Docker 容器中开展项目。下面是我的 dockerfile,效果很好。我的构建使用中间容器在主项目之前构建所有货物容器。除非我更新依赖项,否则项目会在本地快速构建。即使依赖项得到重建,在我的旧 macbook pro 上最多也不会超过 10 分钟。
FROM ekidd/rust-musl-builder as builder
WORKDIR /home/rust/
# Avoid having to install/build all dependencies by copying
# the Cargo files and making a dummy src/main.rs
COPY Cargo.toml .
COPY Cargo.lock .
RUN echo "fn main() {}" > src/main.rs
RUN cargo test
RUN cargo build --release
# We need to touch our real main.rs file or else docker will use
# the cached one.
COPY . .
RUN sudo touch src/main.rs
RUN cargo test
RUN cargo build --release
# Size optimization
RUN strip target/x86_64-unknown-linux-musl/release/project-name
# Start building the final image
FROM scratch
WORKDIR /home/rust/
COPY --from=builder /home/rust/target/x86_64-unknown-linux-musl/release/project-name .
ENTRYPOINT ["./project-name"]
但是,当我将我的项目设置为通过 google 云构建从 github 存储库自动构建时,我震惊地发现构建花费了将近 45 分钟!我想如果我为中间容器正确设置了缓存,至少可以节省一些时间。即使构建器成功地提取了缓存的图像,它似乎也没有使用它并且总是从头开始构建中间容器。这是我的 cloudbuild.yaml:
steps:
- name: gcr.io/cloud-builders/docker
args:
- "-c"
- >-
docker pull $_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest
|| exit 0
id: Pull
entrypoint: bash
- name: gcr.io/cloud-builders/docker
args:
- build
- "-t"
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
- "--cache-from"
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
- .
- "-f"
- Dockerfile
id: Build
- name: gcr.io/cloud-builders/docker
args:
- push
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
id: Push
- name: gcr.io/google.com/cloudsdktool/cloud-sdk
args:
- run
- services
- update
- $_SERVICE_NAME
- "--platform=managed"
- "--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
- >-
--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS
- "--region=$_DEPLOY_REGION"
- "--quiet"
id: Deploy
entrypoint: gcloud
timeout: 3600s
images:
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
options:
substitutionOption: ALLOW_LOOSE
我正在寻找关于我在我的 cloudbuild.yaml 中做错了什么的任何信息,以及关于如何加速我的云构建的提示,考虑到它在本地是如此之快。理想情况下,我想坚持使用 google 云,但如果有另一个 CI 服务可以更好地处理 rust/docker 这样的构建,我愿意切换。
在速度方面有两点需要考虑:
在你的(甚至是旧的)macbook pro 上,
- 你有多核超线程CPU
- CPU 在 Turbo 模式下最高可达 3.5Ghz
云端构建
- 每个构建只有一个 vCPU(默认)
- vCPU是“服务器设计CPU”:没有高端性能,但稳定一致的性能,大约2.1Ghz(在turbo模式下略多)
所以,性能的差异是显而易见的。为了加快构建速度,我建议使用 the machine type option:
...
...
options:
substitutionOption: ALLOW_LOOSE
machineType: 'E2_HIGHCPU_8'
应该会更好!
这就是我在 Google Cloud Build 上改进 Rust 项目构建时间所做的工作。不是一个完美的解决方案,但总比没有好:
在 Docker 文件中对您的文件进行类似更改,以便为部门和我自己的来源创建不同的缓存层。
使用 kaniko 来利用缓存(这似乎是您的特定问题)
steps:
- name: 'gcr.io/kaniko-project/executor:latest'
args:
- --destination=eu.gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA
- --cache=true
- --cache-ttl=96h
timeout: 2400s
文档:https://cloud.google.com/build/docs/kaniko-cache
- 将机器类型更改为更高选项,在我的例子中:
options:
machineType: 'E2_HIGHCPU_8'
不过要小心,更改机器类型会影响您的预算,因此您应该考虑这对您的特定项目是否值得。
如果您经常推送您的更改,效果会更好,但老实说仍然不够好。
我对 Rust 比较陌生,但我一直在 Docker 容器中开展项目。下面是我的 dockerfile,效果很好。我的构建使用中间容器在主项目之前构建所有货物容器。除非我更新依赖项,否则项目会在本地快速构建。即使依赖项得到重建,在我的旧 macbook pro 上最多也不会超过 10 分钟。
FROM ekidd/rust-musl-builder as builder
WORKDIR /home/rust/
# Avoid having to install/build all dependencies by copying
# the Cargo files and making a dummy src/main.rs
COPY Cargo.toml .
COPY Cargo.lock .
RUN echo "fn main() {}" > src/main.rs
RUN cargo test
RUN cargo build --release
# We need to touch our real main.rs file or else docker will use
# the cached one.
COPY . .
RUN sudo touch src/main.rs
RUN cargo test
RUN cargo build --release
# Size optimization
RUN strip target/x86_64-unknown-linux-musl/release/project-name
# Start building the final image
FROM scratch
WORKDIR /home/rust/
COPY --from=builder /home/rust/target/x86_64-unknown-linux-musl/release/project-name .
ENTRYPOINT ["./project-name"]
但是,当我将我的项目设置为通过 google 云构建从 github 存储库自动构建时,我震惊地发现构建花费了将近 45 分钟!我想如果我为中间容器正确设置了缓存,至少可以节省一些时间。即使构建器成功地提取了缓存的图像,它似乎也没有使用它并且总是从头开始构建中间容器。这是我的 cloudbuild.yaml:
steps:
- name: gcr.io/cloud-builders/docker
args:
- "-c"
- >-
docker pull $_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest
|| exit 0
id: Pull
entrypoint: bash
- name: gcr.io/cloud-builders/docker
args:
- build
- "-t"
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
- "--cache-from"
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
- .
- "-f"
- Dockerfile
id: Build
- name: gcr.io/cloud-builders/docker
args:
- push
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
id: Push
- name: gcr.io/google.com/cloudsdktool/cloud-sdk
args:
- run
- services
- update
- $_SERVICE_NAME
- "--platform=managed"
- "--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
- >-
--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS
- "--region=$_DEPLOY_REGION"
- "--quiet"
id: Deploy
entrypoint: gcloud
timeout: 3600s
images:
- "$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:latest"
options:
substitutionOption: ALLOW_LOOSE
我正在寻找关于我在我的 cloudbuild.yaml 中做错了什么的任何信息,以及关于如何加速我的云构建的提示,考虑到它在本地是如此之快。理想情况下,我想坚持使用 google 云,但如果有另一个 CI 服务可以更好地处理 rust/docker 这样的构建,我愿意切换。
在速度方面有两点需要考虑:
在你的(甚至是旧的)macbook pro 上,
- 你有多核超线程CPU
- CPU 在 Turbo 模式下最高可达 3.5Ghz
云端构建
- 每个构建只有一个 vCPU(默认)
- vCPU是“服务器设计CPU”:没有高端性能,但稳定一致的性能,大约2.1Ghz(在turbo模式下略多)
所以,性能的差异是显而易见的。为了加快构建速度,我建议使用 the machine type option:
...
...
options:
substitutionOption: ALLOW_LOOSE
machineType: 'E2_HIGHCPU_8'
应该会更好!
这就是我在 Google Cloud Build 上改进 Rust 项目构建时间所做的工作。不是一个完美的解决方案,但总比没有好:
在 Docker 文件中对您的文件进行类似更改,以便为部门和我自己的来源创建不同的缓存层。
使用 kaniko 来利用缓存(这似乎是您的特定问题)
steps:
- name: 'gcr.io/kaniko-project/executor:latest'
args:
- --destination=eu.gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA
- --cache=true
- --cache-ttl=96h
timeout: 2400s
文档:https://cloud.google.com/build/docs/kaniko-cache
- 将机器类型更改为更高选项,在我的例子中:
options:
machineType: 'E2_HIGHCPU_8'
不过要小心,更改机器类型会影响您的预算,因此您应该考虑这对您的特定项目是否值得。
如果您经常推送您的更改,效果会更好,但老实说仍然不够好。