You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Google Cloud Build的bash脚本启动的容器中挂载卷?

问题场景

我有如下cloudbuild.yaml文件:

steps:
  - name: 'gcr.io/cloud-builders/gsutil'
    args: [ "-m", "rsync", "-r", "gs://${_BUCKET}/maven-repository", "/cache/.m2" ]
    volumes:
      - path: '/cache/.m2'
        name: 'm2_cache'
  - name: docker/compose:debian-1.29.2
    entrypoint: bash
    args:
      - -c
      - |
        ./test.sh
    volumes:
      - path: '/cache/.m2'
        name: 'm2_cache'
    timeout: 2700s

substitutions:
  _BUCKET: 'my-bucket'

第一步从GCS下载包含Artifact Registry Maven仓库凭据的settings.xml文件,这对后续构建至关重要。第二步执行test.sh脚本,脚本内容如下:

#!/bin/bash

echo "### [Host] Contents in /cache/.m2"
ls -la /cache/.m2

mkdir ~/test
echo "Johan" > ~/test/ikk.txt

echo "### [Host] Contents in ~/test"
ls -la ~/test

docker run --rm -v /cache/.m2:/cache/.m2 -v ~/test:/root/test -w /usr/src/somewhere ubuntu bash -c 'echo "### [Docker] Contents in /cache/.m2" && ls -la /cache/.m2 && echo "### [Docker] Contents in /root/test" && ls -la /root/test'

在Google Cloud Build中运行时,脚本启动的ubuntu容器内挂载的目录为空;但本地运行时容器能正常挂载并访问文件。请问如何在Google Cloud Build中实现容器内的卷挂载?

原因及解决方案

核心问题

Google Cloud Build的每个构建步骤本身运行在一个Docker容器(外层容器)中,而你在步骤内执行docker run时,调用的是Cloud Build宿主机的Docker守护进程。此时用-v /cache/.m2:/cache/.m2挂载的是宿主机的路径,而非外层容器的路径——外层容器的/cache/.m2和~/test并不存在于宿主机上,所以新启动的ubuntu容器挂载到的是空目录。

可行解决办法

1. 使用Cloud Build工作区目录(最简单)

Cloud Build默认会把代码仓库的工作区挂载到所有步骤容器的/workspace目录,这个目录在宿主机和步骤容器之间是共享的。修改路径到/workspace下即可:

修改cloudbuild.yaml第一步:

steps:
  - name: 'gcr.io/cloud-builders/gsutil'
    args: [ "-m", "rsync", "-r", "gs://${_BUCKET}/maven-repository", "/workspace/maven-cache" ]
  - name: docker/compose:debian-1.29.2
    entrypoint: bash
    args:
      - -c
      - |
        ./test.sh
    timeout: 2700s

修改test.sh:

#!/bin/bash

echo "### [Host] Contents in /workspace/maven-cache"
ls -la /workspace/maven-cache

mkdir /workspace/test
echo "Johan" > /workspace/test/ikk.txt

echo "### [Host] Contents in /workspace/test"
ls -la /workspace/test

docker run --rm -v /workspace/maven-cache:/cache/.m2 -v /workspace/test:/root/test -w /usr/src/somewhere ubuntu bash -c 'echo "### [Docker] Contents in /cache/.m2" && ls -la /cache/.m2 && echo "### [Docker] Contents in /root/test" && ls -la /root/test'

2. 使用Cloud Build全局缓存卷(推荐用于跨步骤缓存)

如果需要在多个构建步骤之间复用缓存,可以配置全局缓存卷,它会直接挂载到宿主机,这样docker run时能直接访问:

修改cloudbuild.yaml:

steps:
  - name: 'gcr.io/cloud-builders/gsutil'
    args: [ "-m", "rsync", "-r", "gs://${_BUCKET}/maven-repository", "/cache/.m2" ]
  - name: docker/compose:debian-1.29.2
    entrypoint: bash
    args:
      - -c
      - |
        ./test.sh
    timeout: 2700s

substitutions:
  _BUCKET: 'my-bucket'

options:
  volumes:
    - name: 'm2_cache'
      path: '/cache/.m2'

修改test.sh(把测试目录也放到全局缓存路径下):

#!/bin/bash

echo "### [Host] Contents in /cache/.m2"
ls -la /cache/.m2

mkdir /cache/test
echo "Johan" > /cache/test/ikk.txt

echo "### [Host] Contents in /cache/test"
ls -la /cache/test

docker run --rm -v /cache/.m2:/cache/.m2 -v /cache/test:/root/test -w /usr/src/somewhere ubuntu bash -c 'echo "### [Docker] Contents in /cache/.m2" && ls -la /cache/.m2 && echo "### [Docker] Contents in /root/test" && ls -la /root/test'

3. 挂载步骤容器的文件系统(不推荐)

如果必须使用步骤内的命名卷,可以通过挂载步骤容器的文件系统到新容器,但需要获取步骤容器的ID,这种方法依赖Cloud Build底层实现,稳定性差:

# 在test.sh中添加
CONTAINER_ID=$(hostname)
docker run --rm -v /var/lib/docker/containers/$CONTAINER_ID/mounts/merged/cache/.m2:/cache/.m2 -v /var/lib/docker/containers/$CONTAINER_ID/mounts/merged/root/test:/root/test ...

不建议生产环境使用这种方法,因为Cloud Build的容器存储路径可能会变化。


内容的提问来源于stack exchange,提问作者Johan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:15:35