Include Git Commit Id In Docker Container Build

2022-07-08
Docker
Git
containers
devops

The Problem

When working on containerizing an API service with Docker for the CI/CD pipeline, I needed to include into container current Git commit ID and branch - so I could know what code is running in production by just asking the API to return these values.

Essentially there are two simple ways to do it:

The first is kinda simpler to implement and looks contained to Dockerfile (becasue I can bake Git commands and file creation inside Dockerfile), but has several downsides:

  • it requires loading .git inside Docker image, even if only for build stage - it takes time. And it's easy to let the whole repo to slip through into container image.
  • .git might be restricted in .dockerignore, and removing it from there might have undesirable consequences later.
  • storing things in .env promotes storing env in file, which is not too bad for a git commit ID, but a larger potential security issue for credentials.

The Solution

So I chose to store in env variables, which required following:

  • Specifying input parameters via ARG instruction, like so:
    ARG GIT_COMMIT_BRANCH
    ARG GIT_COMMIT_ID
    
  • Setting them into environment variables inside the container image:
    ENV GIT_COMMIT_BRANCH=$GIT_COMMIT_BRANCH
    ENV GIT_COMMIT_ID=$GIT_COMMIT_ID
    
    Note: if you have several stages in Dockerfile, ARG and ENV should be at the same stage as final CMD instruction.
  • Identifying Git commands to get branch name and commit ID:
    git branch --show-current
    git rev-parse --short HEAD
    
  • provide arg values as input parameters for docker build, like so:
    docker build --build-arg GIT_COMMIT_BRANCH=`git branch --show-current` --build-arg GIT_COMMIT_ID=`git rev-parse --short HEAD` -t containername
    

And that did it - I get the required information when launching docker build inside Git repository, where I invariably have repository information, and pass it to the build process that bakes it into the container image so it stays the same for each instance and is available for the application code inside container to use however it pleases.