Search code examples
dockergithubdockerfilegithub-actionscicd

How to access a subset of keys among the labels in the JSON object returned by docker/metadata-action Github action


I'm trying to combine docker/metadata-action and docker/build-push-action in a Github Actions workflow file according to the docs to publish a Docker image.

The problem that I'm having is that I want to only select a subset of labels returned by metadata-action as the labels to be applied to the final Docker image.

This is how my workflow looks like

name: Build Docker Image and Publish to Registry

on:
  workflow_dispatch:
  push:
    branches:
      - main

permissions:
  contents: read
  packages: write

env:
  DOCKER_REGISTRY: ghcr.io
  DOCKER_IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-publish-docker-image:
    name: Build and publish the Docker image
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository code
        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

      - name: Login to Docker registry
        uses: docker/login-action@v2
        with:
          registry: ${{ env.DOCKER_REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=sha,event=workflow_dispatch

      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./Dockerfile
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

This works, except I want to limit the set of labels that will be applied to the final Docker image to only org.opencontainers.image.created and org.opencontainers.image.revision and leave the rest to the default ones set in the Dockerfile.

I tried the following, but it failed because I guess there is a syntax error.

          labels: |
            org.opencontainers.image.created=${{ steps.meta.outputs.labels."org.opencontainers.image.created" }}
            org.opencontainers.image.revision=${{ steps.meta.outputs.labels."org.opencontainers.image.revision" }}

According to the workflow logs, the JSON output of metadata-action looks like this:

{
  "tags": [
    "ghcr.io/user/repo:main",
    "ghcr.io/user/repo:sha-22afbbc"
  ],
  "labels": {
    "org.opencontainers.image.created": "2023-06-14T11:03:48.368Z",
    "org.opencontainers.image.description": "Repo",
    "org.opencontainers.image.licenses": "",
    "org.opencontainers.image.revision": "22afbbca4957b358f0bbfba9936e42bfac08d3b3",
    "org.opencontainers.image.source": "https://github.com/user/repo",
    "org.opencontainers.image.title": "repo",
    "org.opencontainers.image.url": "https://github.com/user/repo",
    "org.opencontainers.image.version": "main"
  }
}

How can I achieve this?


Solution

  • Although @Operator 's answer works, I found out that there is a cleaner way to achieve this:

      labels: |
        org.opencontainers.image.created=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
        org.opencontainers.image.revision=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}
        org.opencontainers.image.version=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}