Search code examples
dockergithub-actions

Is it possible to use Docker for Linux in a matrix of operating systems?


GitHub Actions let us define matrices to launch several variations of a single job. For instance for starting a job on two operating systems:

name: Build
on:
  push
    branches: [ main ]
jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - (…)

GitHub Actions also let us use a Docker container on Linux:

name: Build
on:
  push
    branches: [ main ]
jobs:
  build:
    runs-on: ubuntu-latest
    container: my-docker/container:0.1.0
    steps:
      - (…)

Is it possible to use both at the same time: running a job on several operating systems using matrices, and using a Docker container specifically for Linux? Something among the lines of (this code is invalid):

name: Build
on:
  push
    branches: [ main ]
jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    container:
      if: matrix.os == 'ubuntu-latest'
      image: my-docker/container:0.1.0
    steps:
      - (…)

This code is not correct because container cannot have a if keyword. If I remove the if, the code is correct but the job will fail on macOS runners (which cannot run Docker). How do I enable container for Linux and disable it for everything else? I found no information at all about this use case in the documentation.


Solution

  • I think you could do something like this:

    name: Build
    on:
      push:
        branches: [ main ]
    env:
      WITH_IMAGE: '{"image": "my-docker/container:0.1.0"}'
      NO_IMAGE: '{"image": null}'
    jobs:
      build:
        strategy:
          matrix:
            os: [ubuntu-latest, macos-latest]
            container: [WITH_IMAGE, NO_IMAGE]
            exclude:
              - os: ubuntu-latest
                container: NO_IMAGE
              - os: macos-latest
                container: WITH_IMAGE
        runs-on: ${{ matrix.os }}
        container: ${{ fromJSON(env[matrix.container]) }}
        steps:
          - (…)
    

    I haven't tested this, so it may need some tweaks, but hopefully it conveys the gist of the solution. This is based on this GitHub documentation and a similar issue I encountered recently: Conditional use of container depending on the group it runs-on for GitHub Actions

    Essentially, it uses exclusions so you only get the combinations you want, then passes a null image to container when you don't want to use a container.