Let a .NET Docker image know its version using docker/build-push-action

557 Views Asked by At

I have a .NET 6.0 Web API and want it to know its version. To publish the Docker images I use Github Actions docker/[email protected]. I tried using MinVer which would exactly meet my needs as it is using the latest git version tag and adds the number of commits since that version as last digit. But as the docker/[email protected] does not have the full Git environment, Minver can not extract the version number of the Git tags while the image is built. It would be possible to use a CLI tool to extract the version before creating the Docker image:

    - name: install minver-cli
      run: dotnet tool install --global minver-cli

    - name: get version
      run: echo "MINVERVERSIONOVERRIDE=$(minver --tag-prefix v --verbosity e)" >> $GITHUB_ENV 

    - name: echo environementvariable
      run: echo ${{ env.MINVERVERSIONOVERRIDE }}

If MINVERVERSIONOVERRIDE does exist as environment variable at build time, MinVer does not try to extract the version of the git history but just use that version. But it does not look like this environment variable exists in the docker/[email protected].

Is there any other way to use version numbers based on the git tags when creating a Docker image?

3

There are 3 best solutions below

5
On BEST ANSWER

Your issue is that the Github Actions checkout action uses 1 as the default value for the fetch-depth argument which means that your workflow has only the latest commit available. If the latest tag is not on this commit, minver will not find it.

The solution is to set fetch-depth to 0 (for fetching all commits in the repo) or any other appropriate value. See here for more details.

Edited on Aug 26th 2022 as per the below comments:

First, you write that if MINVERBUILDMETADATA is set, MinVer will not try to calculate the version again. This is wrong. It's the MINVERVERSIONOVERRIDE environment variable which has to be set for this purpose.

Said this, this is how you can pass the calculated version value into the container image:

Put this step somewhere above the docker/build-push-action action in your workflow yml file:

- name: Calculate version
  uses: thefringeninja/[email protected]
  id: version
  with:
    tag-prefix: v

Then pass the version as a build argument to the docker file like this:

- name: Build and push Docker image
  uses: docker/build-push-action@v3
  with:
    build-args: MINVERVERSIONOVERRIDE=${{ steps.version.outputs.version }}

Finally use the value in your Dockerfile by adding the following line between the FROM and where you build your project:

ARG MINVERVERSIONOVERRIDE

Background:
ARG sets an environment variable which is available when building the docker image.

0
On

2023 Update:

It became easier with dotnet publish being able to build and push container images without Dockerfile.

First, add a package reference for container build:

<PackageReference Include="Microsoft.NET.Build.Containers" Version="7.0.302"/>

Keep in mind that there will be new versions, so you can just add the NuGet package using dotnet CLI or your IDE.

Then, add this section, so it runs after MinVer:

<Target Name="Container" AfterTargets="MinVer">
    <PropertyGroup>
        <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
        <ContainerImageName>foo/bar</ContainerImageName>
        <ContainerImageTags>$(MinVerVersion);latest</ContainerImageTags>
        <ContainerRegistry>registry.hub.docker.com</ContainerRegistry>
    </PropertyGroup>
</Target>

Run publish:

dotnet publish --runtime linux-x64 -p:PublishProfile=DefaultContainer --self-contained

You can also put the container runtime as a property to the same property group like this, my example doesn't have it as I build for different architectures and push the combined manifest manually using Docker.

<ContainerRuntimeIdentifier>linux-x64</ContainerRuntimeIdentifier>
1
On

As thefringeninja/[email protected] mentioned in https://stackoverflow.com/a/73472371/8587966 uses set-output which will be disabled on 31st May 2023 I now use the following:

steps:
- name: Checkout
  uses: actions/checkout@v3
  with:
    fetch-depth: 0

- name: Setup dotnet
  uses: actions/setup-dotnet@v2
  with:
    dotnet-version: '7.0.x'

- name: Install minver CLI
  run: dotnet tool install --tool-path ./minver minver-cli --version 4.3.0
      
- name: Calculate version using minver CLI
  id: version
  run: |
      echo "version=$(./minver/minver --default-pre-release-identifiers alpha --tag-prefix v)" >> "$GITHUB_ENV"

- name: Build and push Docker Image
  uses: docker/build-push-action@v4
  with:
    build-args: MINVERVERSIONOVERRIDE=${{ env.version }}
    file: ./projectName/Dockerfile
    platforms: linux/amd64,linux/arm64,linux/arm/v7
    push: true
    tags: user/imagename:latest