如何在 Github Action 中运行已缓存的 Docker 镜像?

16

我不知道如何在Github Actions中运行已缓存的Docker镜像。
我按照关于发布Docker镜像的教程实现了一个任务,该任务会缓存、构建和推送Docker镜像到DockerHub。
我需要构建、缓存和运行镜像,镜像发布是可选的。
我的目标是加速CI工作流程。
这是Github Actions工作流程:

name: CI

# Controls when the action will run. 
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - name: Check Out Repo
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v1 

      - name: Cache Docker layers
        uses: actions/cache@v2
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-

      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with: 
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          context: ./
          file: ./Dockerfile
          builder: ${{ steps.buildx.outputs.name }}
          push: true
          tags: ivan123123/c_matrix_library:latest
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache

      #- name: Run Docker container
      #  run: ???

      # Upload gcovr code coverage report
      - name: Upload GCC Code Coverage Report
        uses: actions/upload-artifact@v2
        with:
          name: coveragereport
          path: ./builddir/meson-logs/coveragereport/
        
      - name: Upload code coverage reports to codecov.io page
        run: bash <(curl -s https://codecov.io/bash) 

编辑:
我没有找到运行缓存的Docker镜像的解决方案,但是我已经成功地使用docker/setup-buildx-action@v1操作每次运行CI工作流时构建缓存镜像。由于镜像被缓存,我们不需要下载每个Docker镜像依赖项,因此将时间从原来的3分钟节省到仅40秒。 以下是Github Actions工作流程:

name: CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Check Out Repo
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v1 

      - name: Cache register
        uses: actions/cache@v2
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ hashFiles('**/Dockerfile') }}

      - name: Build Docker image
        uses: docker/build-push-action@v2
        with:
          context: ./
          file: ./Dockerfile
          builder: ${{ steps.buildx.outputs.name }}
          load: true
          tags: c_matrix_library:latest
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache

      - name: Run Docker container
        run: docker run -v "$(pwd):/app" c_matrix_library:latest

2
你怎么知道你的操作没有使用缓存?有没有错误? - LinPy
该操作使用缓存,但我不知道如何运行缓存的镜像?docker run ivan123123/c_matrix_library 命令会运行缓存的镜像还是从 Dockerhub 拉取镜像?我的目标是加速 CI 工作流程。 - Ivan Vnucec
4个回答

8

如果您想缓存位于Docker仓库中的已发布Docker镜像,可以执行以下操作:

- name: Restore MySQL Image Cache if it exists
  id: cache-docker-mysql
  uses: actions/cache@v3
  with:
    path: ci/cache/docker/mysql
    key: cache-docker-mysql-5.7

- name: Update MySQL Image Cache if cache miss
  if: steps.cache-docker-mysql.outputs.cache-hit != 'true'
  run: docker pull mysql:5.7 && mkdir -p ci/cache/docker/mysql && docker image save mysql:5.7 --output ./ci/cache/docker/mysql/mysql-5.7.tar

- name: Use MySQL Image Cache if cache hit
  if: steps.cache-docker-mysql.outputs.cache-hit == 'true'
  run: docker image load --input ./ci/cache/docker/mysql/mysql-5.7.tar

- name: Start containers
  run: docker compose up -d

当使用docker-compose up运行时,如果一个服务使用Docker镜像mysql:5.7,它会跳过下载步骤。

4
这个问题现在有点老了,但我找到了使用docker/build-push-action构建的镜像在后续步骤中运行的文档方式。简而言之,你需要设置一个本地注册表。
下面的yaml已经直接从这里复制粘贴。
name: ci

on:
  push:
    branches:
      - 'main'

jobs:
  docker:
    runs-on: ubuntu-latest
    services:
      registry:
        image: registry:2
        ports:
          - 5000:5000
    steps:
      -
        name: Checkout
        uses: actions/checkout@v3
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        with:
          driver-opts: network=host
      -
        name: Build and push to local registry
        uses: docker/build-push-action@v3
        with:
          context: .
          push: true
          tags: localhost:5000/name/app:latest
      -
        name: Inspect
        run: |
          docker buildx imagetools inspect localhost:5000/name/app:latest

2

我认为没有实际的方法来运行您缓存的图像,因此这可能无法完全回答您的问题。

但是,您可以使用Github的缓存来加快构建速度。我已经发布了一个完整的教程,您可以在这里阅读:here

总结一下,您可以设置Docker buildx,然后使用build-push-action与GH缓存一起使用:

  - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v1

  - name: Build and push
    uses: docker/build-push-action@v2
    with:
      context: .
      file: ./Dockerfile
      push: true
      tags: ivan123123/c_matrix_library:latest
      cache-from: type=gha
      cache-to: type=gha

编辑

刚刚在构建推送操作中发现了一个对你有用的参考:

https://github.com/docker/build-push-action/blob/master/docs/advanced/share-image-jobs.md


谢谢您的回答,但我认为我已经在我的问题的“编辑”部分发布了一个类似于您的“解决方案”的解决方法。 - Ivan Vnucec
它们相似...但是差异非常大。请注意缓存参数非常不同。您可以前往构建推送文档并花些时间阅读那里的解释。 - m33n

1

编辑:

正如Romain在评论中提到的那样。最初的解决方案将在工作流程开始时提取图像,因此不会使用在工作流程期间构建的图像。唯一的解决方案似乎是在步骤中自己运行docker run


- name: Run my docker image
  run: >
    docker run -t ivan123123/c_matrix_library:latest
    ...

顺便说一下,如果您在工作中使用服务,则使用此解决方案可能会变得有些复杂。在这种情况下,容器与服务容器之间的网络将会有问题。

原始答案:

要运行该镜像,您可以使用以下命令:


- name: Run my docker image
  uses: docker://ivan123123/c_matrix_library:latest
  with:
    entrypoint: ...
    args: ...
entrypointargs是可选的。你可以在这里找到更多信息。但有一个限制,就是你只能在uses字段中使用任何变量或上下文。你只能硬编码图像的名称和标签。

1
"uses" 引用的 Docker 镜像是从 DockerHub 拉取的,这是在设置作业时非常开始就完成的,因此我认为你不能将其缓存。如果你想使用刚构建的 Docker 镜像,则需要显式调用 docker run。 - Romain Prévost
1
@RomainPrévost 是的,我刚刚意识到了。很抱歉,伊万,但我认为我的答案不是正确的解决方案。就像Romain提到的那样,它在工作流程开始时拉取图像。 - ITChap
我尝试缓存一个文件夹,其中保存了构建的Docker镜像,然后像运行任何其他Docker镜像一样运行它,但出于某种原因我找不到路径。 - Ivan Vnucec
@IvanVnucec 也许你可以尝试使用 https://docs.docker.com/engine/reference/commandline/save/ 将镜像保存到任何你想要的地方。 - ITChap
我可能会尝试一下,一旦我有了可行的解决方案,我就会编辑我的问题。我认为 docker/build-push-action@v2 Github Action 隐式地进行保存和加载(请参见我的编辑后的问题)。 - Ivan Vnucec
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接