【问题标题】:Build docker image locally in GitHub Actions using docker/build-push-action使用 docker/build-push-action 在 GitHub Actions 中本地构建 docker 映像
【发布时间】:2021-01-01 08:04:26
【问题描述】:

我的项目中有几个 Dockerfile。一种是用于构建basic 图像,其中包含一些业务级别的抽象。其他人正在基于basic 图像构建服务。

所以在我的服务的 Dockerfile 中,我有类似的东西

FROM my-project/base
# Adding some custom logic around basic stuff

我使用 GitHub Actions 作为我的 CI/CD 工具。 起初我有一个步骤将 docker 安装到我的工作人员中,然后运行类似:

- name: Build base image
  working-directory: business
  run: docker build -t my-project/base .

- name: Build and push service
  working-directory: service
  run: |
    docker build -t my-ecr-repo/service .
    docker push my-ecr-repo/service

但后来我找到了 docker/build-push-action 并决定在我的管道中使用它:

- name: Build business-layer container
  uses: docker/build-push-action@v2
  with:
    load: true
    tags: my-project/base
    context: business
    file: business/Dockerfile

- name: Build service
  uses: docker/build-push-action@v2
  with:
    push: true
    tags: my-ecr-repo/service
    context: service
    file: service/Dockerfile

目前,第二步尝试下载docker.io/my-project/base,显然做不到,因为我从不推送基础镜像:

ERROR: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed

问题是: 构建映像的正确方法是什么,以便通过以下构建步骤在本地访问它?

PS: 我不想将我的裸体basic 图像推到任何地方。

【问题讨论】:

    标签: docker github-actions


    【解决方案1】:

    在构建过程中使用本地映像没有任何特殊步骤。 Docker 总是在进入注册表之前检查您在本地拥有的内容。如果您在一个会话中完成这两个步骤并且没有在某处打错字 - 它就可以正常工作。

    现在,如果不是这样,则只剩下两个可能的问题来源:要么是您构建这些图像的环境,要么是您使用的操作。尝试在ubuntu-latest 上运行,看看是否有任何变化以消除第一个。

    我还可以为您提供两种解决方案,但您可能不会同时喜欢它们:

    1.使用临时本地注册表。我在您使用的操作的 readme 页面上找到了本指南,并为您的代码稍微更改了它:

    jobs:
      local-registry:
        runs-on: ubuntu-latest
        services:
          registry:
            image: registry:2
            ports:
              - 5000:5000
        steps:
          -
            name: Set up QEMU
            uses: docker/setup-qemu-action@v2
          -
            name: Set up Docker Buildx
            uses: docker/setup-buildx-action@v1
            with:
              driver-opts: network=host
          -
            name: Build business-layer container
            uses: docker/build-push-action@v2
            with:
              load: true
              tags: localhost:5000/my-project/base
              context: business
              file: business/Dockerfile
          - 
            name: Build service
            uses: docker/build-push-action@v2
            with:
              push: true
              tags: my-ecr-repo/service
              context: service
              file: service/Dockerfile
    
    

    当然,您必须将service/Dockerfile 更新为指向localhost:5000/my-project/base 而不仅仅是my-project/base。

    2。使用简单的 shell 而不是 build-push-action。 如果您的旧代码有效而该操作无效,那么问题可能出在操作上。

    【讨论】:

      【解决方案2】:

      我相信您需要在基本图像和最终图像中设置load: true。这改变了使用本地 docker 引擎处理图像的行为。如果您这样做,我相信您需要单独进行推送,例如:

      - name: Build business-layer container
        uses: docker/build-push-action@v2
        with:
          load: true
          tags: my-project/base
          context: business
          file: business/Dockerfile
      
      - name: Build service
        uses: docker/build-push-action@v2
        with:
          load: true
          tags: my-ecr-repo/service
          context: service
          file: service/Dockerfile
      
      - name: push service
        run: |
          docker push my-ecr-repo/service
      

      另一种选择是使用本地注册表。这具有支持多平台构建的优势。但是您需要使用基本映像从 load 切换到 push,并且我会将基本映像作为构建 arg 传递,以使 Github 操作之外的用例更容易,例如:

      jobs:
        local-registry:
          runs-on: ubuntu-latest
          services:
            registry:
              image: registry:2
              ports:
                - 5000:5000
          steps:
            - name: Login to DockerHub
              uses: docker/login-action@v1 
              with:
                username: ${{ secrets.DOCKERHUB_USERNAME }}
                password: ${{ secrets.DOCKERHUB_TOKEN }}
            # qemu should only be needed for multi-platform images
            - name: Set up QEMU
              uses: docker/setup-qemu-action@v2
            - name: Set up Docker Buildx
              uses: docker/setup-buildx-action@v1
              with:
                driver-opts: network=host
            - name: Build business-layer container
              uses: docker/build-push-action@v2
              with:
                push: true
                tags: localhost:5000/my-project/base
                context: business
                file: business/Dockerfile
            - name: Build service
              uses: docker/build-push-action@v2
              with:
                push: true
                tags: my-ecr-repo/service
                context: service
                file: service/Dockerfile
                build-args: |
                  BASE_IMAGE=localhost:5000/my-project/base
      

      然后您的 Dockerfile 将允许将基础映像指定为构建参数:

      ARG BASE_IMAGE=my-project/base
      FROM ${BASE_IMAGE}
      # ...
      

      【讨论】:

        【解决方案3】:

        github操作docker/setup-buildx-action@v1默认驱动docker-containeras documented。
        这意味着默认情况下,构建将在容器中运行,因此图像在操作之外将不可用。
        解决方法是将驱动设置为docker:

             ...
        
              - name: Set up Docker Buildx
                uses: docker/setup-buildx-action@v1
                with:
                  driver: docker # defaults to "docker-containerized"
        
              - name: Build business-layer container
                uses: docker/build-push-action@v2
                with:
                  # using "load: true" forces the docker driver
                  # not necessary here, because we set it before
                  #load: true
                  tags: my-project/base:latest
                  context: business
                  file: business/Dockerfile
        
              - name: Build service
                uses: docker/build-push-action@v2
                with:
                  # using "push: true" will lead to error:
                  # Error: buildx call failed with: auto-push is currently not implemented for docker driver
                  # so you will have to follow the solution outlined here:
                  # https://github.com/docker/build-push-action/issues/100#issuecomment-715352826
                  # and push the image manually following the build
                  #push: true
                  tags: my-ecr-repo/service:latest
                  context: service
                  file: service/Dockerfile
        
              # list all images, you will see my-ecr-repo/service and my-project/base
              - name: Look up images
                run: docker image ls
        
              # push the image manually, see above comment
              - name: Push image
                run: docker push my-ecr-repo/service:latest
        
             ...
        

        【讨论】:

        • 如果你想使用 cache-from/cache-to 这个方法不行
        猜你喜欢
        • 2022-11-11
        • 2022-08-24
        • 2021-08-24
        • 2019-07-05
        • 2023-02-17
        • 2021-11-22
        • 2022-11-10
        • 2021-12-23
        • 1970-01-01
        相关资源
        最近更新 更多