github actions 单repo build多个docker image

于 2023-12-15 发布

示例repo:docker-jekyll - sieveLau

多个docker image可以单纯是tag不一样,也可以是连名字都不一样。至于platform不一样的话,docker/build-push-action本身就支持这个功能。

原理是使用github actions的matrix功能把Dockerfile跟其他属性连接起来,从而生成多个image。比如示范repo做的就是build两个tag出来。

./
|-- .github/
│   `-- workflows/
│       `-- docker.yaml
├── Dockerfile.cli
├── Dockerfile.server
└── entry.sh

显然Dockerfile.cli是给clitag用的。我们有两个tag,所以就是两个Dockerfile,用一个1x2的matrix来跑。首先我们需要把对应关系定义好,用matrix的include来进行定义:

1
2
3
4
5
6
7
8
9
10
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - dockerfile: ./Dockerfile.cli
            tag: sievelau/jekyll:cli
          - dockerfile: ./Dockerfile.server
            tag: sievelau/jekyll:server

有了这个matrix定义,github actions在运行时就会自动创建两个jobs,各带一组变量:

1
2
3
4
5
6
7
8
9
10
11
12
{
    "matrix": {
        "dockerfile":"./Dockerfile.cli",
        "tag":"sievelau/jekyll:cli"
    }
}
{
    "matrix": {
        "dockerfile":"./Dockerfile.server",
        "tag":"sievelau/jekyll:server"
    }
}

那么自然我们就可以在docker/build-push-action里面用${{ matrix.变量名 }}语法来访问对应的文件和tag了。至于build不同架构的image,比如同时build m1用的arm64和普通的amd64,就直接在platforms里面用逗号分隔写上就好。

platform的格式是os/arch,一般来说os直接写linux,然后arch常见的就是amd64、arm64等。不确定的话可以在自己的机上build之后,用docker inspect <image-name>看。

1
2
3
4
5
6
7
8
9
-
  name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    platforms: linux/amd64,linux/arm64
    file: ${{ matrix.dockerfile }}
    push: true
    tags: ${{ matrix.tag }}
完整的workflow
name: Push to DockerHub

on:
  workflow_dispatch:
  push:
    branches:
      - "master"
    paths:
      - "Dockerfile.*"
      - "entry.sh"
      - ".github/**/*"

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - dockerfile: ./Dockerfile.cli
            tag: sievelau/jekyll:cli
          - dockerfile: ./Dockerfile.server
            tag: sievelau/jekyll:server
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      -
        name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKER_TOEKN }}
      -
        name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          file: ${{ matrix.dockerfile }}
          push: true
          tags: ${{ matrix.tag }}

参考:

  1. actions里不同architecture要怎么写:Multi-arch docker images the easy way, with Github Actions - Pablo Romeo
  2. matrix语法:Using a matrix for your jobs - Github
  3. 将jekyll塞进容器里的指导:jekyll-serve

目录