本地运行CodeBuild能否使用非默认Docker桥接网络与存储卷?
本地运行CodeBuild时,程序会自动创建默认Docker网络与存储卷,尝试修改codebuild_build.sh中的docker启动命令、添加--network mylocaltestingnetwork参数后配置并未生效。
当前需要搭配localstack使用,要求CodeBuild本地容器能够访问指定的bridge网络与存储卷;虽然将localstack接入CodeBuild自动创建的agent-resources_default网络可以实现正常访问,但期望通过独立桥接网络实现二者依赖解耦,避免双方依赖对方创建的网络资源。
运行构建的输出日志如下:
$ ./codebuild_build.sh -i public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:3.0 -a codebuild-output/ -b buildspec-local.yml -c -p localstack Build Command: docker run -it -v /var/run/docker.sock:/var/run/docker.sock -e "IMAGE_NAME=public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:3.0" -e "ARTIFACTS=<repo path>/codebuild-output/" --network mylocaltestingnetwork -e "SOURCE=<repo path>" -e "BUILDSPEC=<repo path>/buildspec-local.yml" -e "AWS_CONFIGURATION=<homedir>/.aws" -e "AWS_PROFILE=localstack" -e "INITIATOR=<user>" public.ecr.aws/codebuild/local-builds:latest Removing network agent-resources_default Removing volume agent-resources_source_volume Removing volume agent-resources_user_volume Creating network "agent-resources_default" with the default driver Creating volume "agent-resources_source_volume" with local driver Creating volume "agent-resources_user_volume" with local driver Creating agent-resources_agent_1 ... done Creating agent-resources_build_1 ... done Attaching to agent-resources_agent_1, agent-resources_build_1 agent_1 | [Container] 2022/01/14 15:57:15 Waiting for agent ping agent_1 | [Container] 2022/01/14 15:57:17 Waiting for DOWNLOAD_SOURCE agent_1 | [Container] 2022/01/14 15:57:23 Phase is DOWNLOAD_SOURCE
根因说明
给外层public.ecr.aws/codebuild/local-builds:latest调度容器添加--network参数无效的核心逻辑:该容器仅承担构建流程调度作用,启动后会通过挂载的/var/run/docker.sock直连宿主机Docker接口,硬编码创建固定命名的agent-resources_default网络、agent-resources_source_volume和agent-resources_user_volume两个存储卷,再将实际执行构建任务的agent容器、build容器接入这套自建资源,完全不会继承外层调度容器的网络配置。
推荐方案(无侵入、兼容版本升级)
利用Docker的资源复用逻辑,提前按CodeBuild的固定命名规则创建自定义配置的网络和卷,CodeBuild启动时检测到对应资源已存在,就不会执行删除、重建操作,直接复用预配置的资源:
- 先清理历史自动创建的同名资源,避免冲突:
docker network rm agent-resources_default 2>/dev/null docker volume rm agent-resources_source_volume agent-resources_user_volume 2>/dev/null - 按实际需求创建自定义bridge网络,网络名必须使用
agent-resources_default,创建时可以自定义子网、网关、DNS等所有bridge网络支持的参数,同时提前将localstack容器接入该网络:# 示例:创建自定义配置的bridge网络 docker network create --driver bridge \ --subnet 172.28.0.0/16 \ --gateway 172.28.0.1 \ agent-resources_default # 将已运行的localstack容器接入该网络 docker network connect agent-resources_default <你的localstack容器名> - 按需求创建自定义配置的两个固定命名存储卷,支持配置本地路径挂载、远程存储驱动等参数:
docker volume create agent-resources_source_volume docker volume create agent-resources_user_volume - 直接执行原有
codebuild_build.sh脚本即可,不需要修改脚本内的任何启动参数,CodeBuild会直接复用提前创建的自定义网络和存储卷,构建容器和localstack可以通过容器名直接网络互通。
该方案完全不改动CodeBuild本身的运行逻辑,本质是将CodeBuild硬编码要创建的资源提前按自定义需求配置完成,后续CodeBuild本地构建镜像升级也不会出现兼容问题。使用时不需要让localstack感知CodeBuild的存在,也不需要修改CodeBuild的启动脚本,仅需维护提前创建的公共桥接网络即可,完全满足依赖解耦的要求。
备选方案(自定义资源名,维护成本高)
如果一定要使用自定义命名的网络和存储卷,需要修改local-builds镜像内的docker-compose编排配置:
- 拉取
public.ecr.aws/codebuild/local-builds:latest镜像,启动容器后找到内部的docker-compose.yml文件,将其中硬编码的网络名、卷名替换为自定义名称,同时将网络、卷配置为external类型,关联提前创建好的外部资源。 - 将修改后的容器重新打包为自定义镜像,修改
codebuild_build.sh中引用的local-builds镜像地址为自定义镜像即可。
该方案每次CodeBuild官方更新local-builds镜像时,都需要重新修改配置打包镜像,维护成本较高,非特殊需求不推荐使用。
内容的提问来源于stack exchange,提问作者rockcode

