When deploying containerized applications to cloud environments it is important to be able to know which version you are running. In the past, sometimes it was hard to know if container orchestration systems like kubernetes had picked up your new Docker images. In our production environments, we would specifically reference our deployment tags (eg, some-registry/some-project:1.2
). But for dev environments, we would simply overwrite a dev
tag similar to a latest
tag so that we wouldn’t pollute our registry.
This meant that I wasn’t changing the tag in the kubernetes Deployment
spec, but instead just deleting Pods
and hoping it picked up the new version in the dev environments.
You can use your versioning to help identify container builds, but like my dev case above, sometimes you don’t want to update your “public version” and instead just want to deploy a slightly changed build. Also, you may not want to create a new tag in your registry just for an incremental build. Maybe you reserve them for official releases.
Recently while deploying containers to AWS ECS, I ran into the same issue. Unlike kubernetes where you can easily open a shell to the container, using ECS means your access to the container is limited.
So my solution was to instead just log the current build so that I can verify it is running what I want.
Injecting build info into containers
To do this, I injected the build info into my container when building the container image. Yes, this means you could potentially inject the wrong build info, but it sounded better to me than using Source Link which would require including the .git
source control files in my container image.
In order to make sure I injected the correct build info, I set up my GitHub CI pipeline so that it specifies the current commit hash when building the container:
- name: Build and publish - Player Tracker
uses: docker/build-push-action@v6.9.0
with:
context: .
file: ./src/PlayerStatus/Apps/MlbTheShowForecaster.PlayerStatus.Apps.PlayerTracker/Dockerfile
build-args: |
BUILD_ID=${{ github.sha }}
push: true
tags: |
ghcr.io/${{ github.actor }}/${{ env.IMAGE_NAME }}/player-tracker:${{ env.TAG_NAME }}
labels: ${{ steps.meta.outputs.labels }}
By setting the commit hash as a build argument for the container, BUILD_ID=${{ github.sha }}
, I could use it to set an environment variable on the .NET container in my Dockerfile
.
# .NET Build stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
ARG BUILD_ID
ENV BUILD_ID=${BUILD_ID}
WORKDIR /src
# Build properties
COPY Directory.Build.props .
Notice that I am also copying a file called Directory.Build.props
into the container. This file allows you to customize properties when building your application.
In my case, I was using it to set the version that would be displayed when logging the build info.
<Project>
<PropertyGroup>
<VersionPrefix>0.0.1</VersionPrefix>
<BUILD_ID Condition="'$(BUILD_ID)' == ''">no.build.checksum</BUILD_ID>
<VersionSuffix>$(BUILD_ID)</VersionSuffix>
</PropertyGroup>
</Project>
The line Condition="'$(BUILD_ID)' == ''"
conditionally sets the BUILD_ID value as no.build.checksum
if the ENV variable was not injected into the container. VersionPrefix
and VersionSuffix
both make up the ProductVersion
value.
Combined, the value would be:
v0.0.1-175e0d963058080be862cac028e4aa584b648d27
I can then log this to the console: FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly()!.Location).ProductVersion
. Then all I need to do is just compare this git commit hash to whatever commit was used to build the Docker images. If you do this locally, yes, there is the chance of accidentally setting the wrong commit hash, but since this is automated in my build pipeline, I don’t run into that issue.