docker-composegithub-actionscommand-line-interfacedocker-cligithub-container-registry

How to tag and label an image with docker compose CLI in a github workflows publish.yaml file?


I have a Dockerfile and docker-compose.yml file, and am trying to have the image be built, then published to the Github Container Registry upon a push to the repo. I have a publish.yaml file in .github/workflows, which is where I'm doing it.

My problem is that I want to use the labels and tags that I got from extracting docker metadata in a step in the publish.yaml file, then add those tags and labels to the image via docker compose build. So I can't just put them in the docker-compose file.


My publish.yml file looks like this:

on:
  push: 
    branches: 
      - main
      - docker
    tags:
      - v*

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-publish-image:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      attestations: write

    steps:
      - name: Check out the repo
        uses: actions/checkout@v3

      - name: Setup Docker buildx
        uses: docker/setup-buildx-action@v2

      - name: Log in to GitHub Container registry
        uses: docker/login-action@v2
        with:
          registry: ${{ env.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.REGISTRY }}/${{ env.IMAGE_NAME }}

      - name: Remove and stop docker compose containers
        run: docker compose -f docker-compose.yml down


      ###This is the problem step:###
      - name: Build Docker image with docker compose
        run: docker compose -f docker-compose.yml --progress=plain build --pull --no-cache --tag ${{ steps.meta.outputs.tags }} --label ${{ steps.meta.outputs.labels }}
        

      - name: Push Docker image
        run: docker push ${{ env.REGISTRY }}/{{env.IMAGE_NAME }}:latest

I get an error with the "Build Docker image with docker compose" section in github actions:

unknown flag: --tag Error: Process completed with exit code 16.

since according to the docker compose cli and compose build cli reference docs, it doesn't seem like docker compose build has the --tag or --label options that docker build does.


After looking at this: Docker-compose tagging and pushing, and the docker compose cli reference docs, I am doing it like this now:

  ###This is the problem step:###
  - name: Build Docker image with docker compose
    run: |
      docker compose -f docker-compose.yml --progress=plain build --pull --no-cache 
      docker tag ${{env.IMAGE_NAME }} ${{ steps.meta.outputs.tags }}  
  
  - name: Push Docker image
    run: docker push ${{ env.REGISTRY }}/{{env.IMAGE_NAME }}:latest

But I still don't know how to put the labels from ${{ steps.meta.outputs.labels }} onto it. How do I go about that? Is there a better way to do this overall?

I wanted to use docker/build-push-action@v4 like from the example on this site, but I need it built via compose. And I don't really understand what to do from the answers here: How to tag docker image with docker-compose


Solution

  • The simplest answer to the question is... you can't. Docker-compose CLI can't do what I was asking, so I turned to docker buildx bake, which can add tags and labels with the --set option.

    I ended up using docker/metadata-action along with the docker/bake-action to get what I wanted, instead of docker bake CLI. I did however, include what I believe the CLI equivalent of my docker-action would be.


    The metadata action has {{ $outputs.labels }} and {{ $outputs.tags }}, which I was using originally.

    But it ALSO has outputs of bake files, {{ $outputs.bake-file-tags }} and {{ $outputs.bake-file-labels }}, which you can read more about here: metadata outputs, and you can read more about bake files here.

    Those files, used with the bake action, can apply multiple tags and labels and build and push my image from the docker-compose.yml file I had written.

    Here is my updated yml file:

    steps:
        - name: Checkout the repository
          uses: actions/checkout@v4
    
        - name: Setup Docker buildx
          uses: docker/setup-buildx-action@v3
    
        - name: Log in to GitHub Container registry
          uses: docker/login-action@v3
          with:
            registry: ${{ env.REGISTRY }}
            username: ${{ github.actor }}
            password: ${{ secrets.GITHUB_TOKEN }}
    
        - name: Extract metadata (tags, labels) for Docker
          id: meta
          uses: docker/metadata-action@v3
          with:
            images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
            tags: |
              # tag with version number upon "git push tag"
              type=match,pattern=v(.*),group=1
              # set latest tag for default branch
              type=raw,value=latest,enable={{is_default_branch}}
     
        - name: Build & Push Docker image with Github Bake Action
          uses: docker/bake-action@v4
            with:
              source: . 
              push: true
              pull: true
              files: |
                ./docker-compose.yml
                ${{ steps.meta.outputs.bake-file-tags }}
                ${{ steps.meta.outputs.bake-file-labels }}
              targets: myApp
    

    And here is what I think the CLI equivalent of that last step would be:

        - name: Build Docker image with docker bake
          run: docker buildx bake -f docker-compose.yml -f ${{ steps.meta.outputs.bake-file-tags }} -f ${{ steps.meta.outputs.bake-file-labels }} --progress=plain --pull --push myApp