如何在自托管Bitbucket Pipeline(DinD)中启动宿主机Docker容器?
问题:Bitbucket Pipeline自托管Runner部署容器未在宿主机启动
我负责一个基于Spring Boot的项目,用本地机器作为测试环境,要把它部署为Docker容器。目前正在搭建Bitbucket Pipeline实现从构建到部署的全自动化流程,采用的是同一台机器和Docker实例上的自托管Docker Runner。已经完成了项目构建(mvn编译及Docker镜像构建),并成功将镜像上传至GCP容器注册表。但最后部署步骤的docker run命令虽执行成功,却没有在宿主机的Docker中启动容器。
我理解Runner本身因为挂载了docker.sock具备访问宿主机Docker的权限,但每个Pipeline步骤会创建新的容器,这些步骤容器默认没有docker.sock的访问权限,是不是这样?想请教如何给这些步骤容器赋予该文件的访问权限,或者有没有更优的解决方案。
以下是简化后的流水线配置:
image: maven:3.8.7-openjdk-18 definitions: services: docker: image: docker:dind pipelines: default: # build only for feature branches or so branches: test: # build, docker and upload steps - step: name: Deploy deployment: test image: google/cloud-sdk:alpine runs-on: - 'self.hosted' - 'linux' caches: - docker script: - IMAGE_NAME=$BITBUCKET_REPO_SLUG - VERSION="${BITBUCKET_BUILD_NUMBER}" - DOCKER_IMAGE="${DOCKER_REGISTRY}/${IMAGE_NAME}:${VERSION}" # Authenticating with the service account key file - echo $GCLOUD_API_KEYFILE > ./gcloud-api-key.json - gcloud auth activate-service-account --key-file gcloud-api-key.json - gcloud config set project $GCLOUD_PROJECT # Login with docker and stop old container (if exists) and run new one - cat ./gcloud-api-key.json | docker login -u _json_key --password-stdin https://eu.gcr.io - docker ps -q --filter "name=${IMAGE_NAME}" | xargs -r docker stop - docker run -d -p 82:8080 -p 5005:5005 --name ${IMAGE_NAME} --rm ${DOCKER_IMAGE} services: - docker
解决方案
方案1:为步骤容器挂载宿主机的docker.sock
自托管Runner本身能访问宿主机的docker.sock,但每个步骤的独立容器默认不会挂载这个文件。只需在Deploy步骤中添加volumes配置,将宿主机的/var/run/docker.sock挂载到步骤容器的对应路径,就能让步骤容器直接调用宿主机的Docker引擎。
修改后的Deploy步骤配置:
- step: name: Deploy deployment: test image: google/cloud-sdk:alpine runs-on: - 'self.hosted' - 'linux' caches: - docker # 添加宿主机docker.sock挂载 volumes: - /var/run/docker.sock:/var/run/docker.sock script: - IMAGE_NAME=$BITBUCKET_REPO_SLUG - VERSION="${BITBUCKET_BUILD_NUMBER}" - DOCKER_IMAGE="${DOCKER_REGISTRY}/${IMAGE_NAME}:${VERSION}" - echo $GCLOUD_API_KEYFILE > ./gcloud-api-key.json - gcloud auth activate-service-account --key-file gcloud-api-key.json - gcloud config set project $GCLOUD_PROJECT - cat ./gcloud-api-key.json | docker login -u _json_key --password-stdin https://eu.gcr.io - docker ps -q --filter "name=${IMAGE_NAME}" | xargs -r docker stop - docker run -d -p 82:8080 -p 5005:5005 --name ${IMAGE_NAME} --rm ${DOCKER_IMAGE} services: - docker
这样执行docker run命令时,就会直接在宿主机的Docker环境中启动目标容器。
方案2:直接在Runner宿主机执行部署命令(更简洁)
既然是自托管Runner,也可以跳过步骤容器,直接在Runner宿主机环境中执行部署脚本:
- 移除Deploy步骤的
image配置,Pipeline会直接使用Runner宿主机的环境执行命令 - 提前在Runner宿主机配置好GCloud认证(比如把服务账号密钥放在固定路径)和Docker环境
修改后的步骤示例:
- step: name: Deploy deployment: test runs-on: - 'self.hosted' - 'linux' script: - IMAGE_NAME=$BITBUCKET_REPO_SLUG - VERSION="${BITBUCKET_BUILD_NUMBER}" - DOCKER_IMAGE="${DOCKER_REGISTRY}/${IMAGE_NAME}:${VERSION}" # 直接调用宿主机的gcloud和docker命令 - cat /opt/gcloud-api-key.json | docker login -u _json_key --password-stdin https://eu.gcr.io - docker ps -q --filter "name=${IMAGE_NAME}" | xargs -r docker stop - docker run -d -p 82:8080 -p 5005:5005 --name ${IMAGE_NAME} --rm ${DOCKER_IMAGE}
这种方式无需处理容器挂载,直接利用宿主机已有的环境,更适合自托管场景。
注意事项
- 挂载
docker.sock时需注意权限:确保步骤容器内的用户(比如google/cloud-sdk:alpine默认是root)对挂载的sock文件有读写权限。宿主机上docker.sock的权限通常是root:docker,若容器内用户非root,可能需要将用户加入docker组或调整文件权限。 - 直接在宿主机执行时,要确保Runner宿主机已安装
gcloud和docker,并配置好必要的环境变量或认证信息。
内容的提问来源于stack exchange,提问作者tagtraeumer
相关产品推荐
相关产品推荐

