Gitlab CI DinD 中使用缓存加速 Docker 镜像(多阶段)构建过程

CSDN 中文章不一定能及时更新,欢迎关注我的博客查看最新版本:许盛的博客

参考:
https://andrewlock.net/caching-docker-layers-on-serverless-build-hosts-with-multi-stage-builds—target,-and—cache-from/
https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#make-docker-in-docker-builds-faster-with-docker-layer-caching

背景

gitlab ci 中使用 docker 容器作为 runner时,如果在命令中又需要调用 docker ,这就相当于在 Docker 容器中使用 Docker 了,就是 Docker In Docker,简称 dind

在功能上来说, dind 配置好之后,除了安全性和速度的缺点外,使用起来没有任何问题。

在官方文档上有这样一句描述:

Cache: Each job runs in a new environment. Concurrent jobs work fine, because every build gets its own instance of Docker engine and they don’t conflict with each other. However, jobs can be slower because there’s no caching of layers.

大概意思就是每个 job 都在新的环境中运行,都有自己的 docker 引擎实例,所以并没有层缓存。

这就导致我们在使用 docker build 命令的时候,每次都需要重新拉取 Dockerfile 中依赖的基础镜像,也无法利用上一次构建任务触发后遗留的镜像层缓存,因为宿主机上压根就没有缓存文件。

解决

参考:
Make Docker-in-Docker builds faster with Docker layer caching

最初的想法是,能不能在构建过程中,将镜像缓存层给存到宿主机上,在查阅文档的过程中,发现 docker build 提供了一个 —cache-from 参数,可以指定某个镜像,作为构建过程中的缓存源。

这样的话,思路就有了,因为每次构建完成后,虽然中间的缓存层以及打包出来的镜像,在宿主机上都没有了,但是最终的镜像上传到了公司内的 Harbor 上。

这样每次开始 docker build 之前,将上一次构建的镜像 pull 到本地,然后使用 --cache-from 参数指定为缓存源即可。

例如官方文档提供的 yaml 配置:

image: docker:19.03.12

services:
  - docker:19.03.12-dind

variables:
  # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest

每一次构建开始前,都会将最近的镜像拉取下来,并指定为镜像源。

针对多阶段构建

以上这种方式,针对多阶段构建的情况,其实稍稍有点问题,因为在多阶段构建过程中,最终生成的镜像,只包含了最后一个阶段的镜像层,而之前阶段的镜像层,都丢弃掉了。

这样就算指定了最终的镜像作为缓存源,也无法在前置的构建阶段起到作用。

这时候 docker build—target 参数就起作用了。

使用 —target 参数,可以在构建过程中,指定构建哪个阶段的镜像,这样我们就可以针对单个阶段构建镜像,并 pushharbor 上,并在下次构建时 pull 下来作为缓存源使用。

示例如下:

build: # 构建镜像
  stage: build
  image: docker:stable
  script:
    # 将 builder 镜像拉下来,用作多阶段构建中第一阶段的缓存使用
    - docker pull $HARBOR:builder || true
    # 进行第一阶段构建,产出 builder 镜像,用作下一次的缓存
    - docker build --target builder --cache-from $HARBOR:builder -t $HARBOR:builder -f _ci/Dockerfile .
    # 将 latest 镜像拉下来,用作第二阶段的构建的缓存,根据 Dockerfile 实际情况判断是否需要这一步优化
    - docker pull $HARBOR:latest || true
    # 开始实际的构建
    - docker build --build-arg VERSION_TAG=$CI_COMMIT_TAG --build-arg COMMIT_ID=$CI_COMMIT_SHORT_SHA --cache-from $HARBOR:builder --cache-from $HARBOR:latest -f _ci/Dockerfile -t $HARBOR:$CI_COMMIT_SHORT_SHA .
    - docker push $HARBOR:$CI_COMMIT_SHORT_SHA
    # 上传这一次生成的 builder 镜像
    - docker push $HARBOR:builder
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用 Docker + Jenkins + Gitlab+Harbor 实现自动化构建部署的详细步骤及教学。 1. 安装 Docker 首先需要安装 Docker,可以参考 Docker 官方文档进行安装。 2. 安装 Jenkins Jenkins 是持续集成和持续交付工具,可以在官网下载 Jenkins 安装包,也可以使用 Docker 安装 Jenkins。 使用 Docker 安装 Jenkins 可以使用以下命令: ``` docker run -d -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts ``` 其 `-d` 表示在后台运行,`-p` 表示将容器的端口映射到宿主机上,`-v` 表示将 Jenkins 的数据存储在本地。 3. 安装 Gitlab Gitlab 是代码托管平台,可以在官网下载 Gitlab 安装包,也可以使用 Docker 安装 Gitlab使用 Docker 安装 Gitlab 可以使用以下命令: ``` docker run --detach \ --hostname gitlab.example.com \ --publish 443:443 --publish 80:80 --publish 22:22 \ --name gitlab \ --restart always \ --volume /srv/gitlab/config:/etc/gitlab \ --volume /srv/gitlab/logs:/var/log/gitlab \ --volume /srv/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest ``` 其 `--hostname` 表示 Gitlab 的域名,`--publish` 表示将容器的端口映射到宿主机上,`--name` 表示给容器命名,`--volume` 表示将 Gitlab 的数据存储在本地。 4. 安装 Harbor Harbor 是 Docker 镜像仓库,可以在官网下载 Harbor 安装包,也可以使用 Docker 安装 Harbor。 使用 Docker 安装 Harbor 可以使用以下命令: ``` docker run -d -p 80:80 -p 443:443 --name harbor --restart always -v /data/harbor:/data harbor/harbor:v2.1.4 ``` 其 `-p` 表示将容器的端口映射到宿主机上,`--name` 表示给容器命名,`-v` 表示将 Harbor 的数据存储在本地。在上面的命令,Harbor 的数据存储在 `/data/harbor` 目录下。 5. 配置 Gitlab 登录 Gitlab 后,在项目创建一个 `.gitlab-ci.yml` 文件,用于编写 CI/CD 流程的配置。 下面是一个简单的示例: ``` image: docker:latest services: - docker:dind stages: - build - test - deploy build: stage: build script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA test: stage: test script: - docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA npm test deploy: stage: deploy script: - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest - docker push $CI_REGISTRY_IMAGE:latest ``` 其 `image` 表示使用Docker 镜像,`services` 表示服务容器,`stages` 表示流程的阶段。 在 `build` 阶段使用 Docker 构建镜像,并将镜像推送到 Harbor 。 在 `test` 阶段使用 Docker 运行镜像,并运行测试。 在 `deploy` 阶段,从 Harbor 拉取最新的镜像,并使用 `docker tag` 命令将其打上 `latest` 标签,然后将镜像推送到 Harbor 。 6. 配置 Jenkins 登录 Jenkins 后,在插件管理安装 GitlabDocker、Harbor 插件。 然后创建一个新的 Jenkins 任务,选择 Gitlab 项目,并配置 Gitlab 的 Webhook,以触发 Jenkins 的构建。 在任务的配置,选择 Gitlab 作为版本控制工具,配置 Gitlab 仓库的地址和访问凭证。 在构建环境,选择 Docker,并配置 Docker镜像仓库地址和凭证。 在构建步骤,选择执行 Shell 命令,并编写构建脚本。 下面是一个简单的示例: ``` #!/bin/bash docker build -t $DOCKER_REGISTRY_IMAGE:$BUILD_NUMBER . docker push $DOCKER_REGISTRY_IMAGE:$BUILD_NUMBER docker tag $DOCKER_REGISTRY_IMAGE:$BUILD_NUMBER $DOCKER_REGISTRY_IMAGE:latest docker push $DOCKER_REGISTRY_IMAGE:latest ``` 其 `$BUILD_NUMBER` 表示 Jenkins 的构建号,`$DOCKER_REGISTRY_IMAGE` 表示 Docker 镜像仓库的地址。 7. 测试 在 Gitlab 进行代码提交,触发 Jenkins 的构建流程。可以在 Jenkins 的控制台查看构建日志,查看构建是否成功。可以在 Harbor 的镜像仓库查看构建镜像是否成功推送。 8. 总结 使用 Docker + Jenkins + Gitlab+Harbor 实现自动化构建部署,可以提高软件开发的效率和质量,减少手动操作带来的错误。这里介绍了一个简单的示例,实际的项目需要根据实际情况进行配置和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值