1. Overview

In this tutorial, we’ll explore how to retrieve the commit hash from a running Docker container. This is particularly useful when debugging or verifying the exact version of the code running in our containerized applications.

2. Understanding the Importance of Commit Hash

The commit hash uniquely identifies a specific state of our codebase in version control. Having this information readily accessible can be critical for tracking changes, debugging, and ensuring consistency across different environments. A typical commit hash looks like this: ce85e2ebe299cf9a8237556c86dbcaaa2d571a3e.

3. Tagging Docker Images with Commit Hash

When building Docker images, it’s a common practice to tag them with the commit hash. This provides a clear linkage between the image and the exact state of the source code it was built from.

3.1. Building and Tagging an Image

To tag our Docker image with the commit hash during the build process, we can use the following command:

$ docker build --build-arg GIT_COMMIT=$(git rev-parse HEAD) -t my_image:$(git rev-parse HEAD)

In this command, –build-arg GIT_COMMIT=$(git rev-parse HEAD) passes the current commit hash to the Docker build process, and -t my_image:$(git rev-parse HEAD) tags the built image with the same commit hash, creating a direct link between the Docker image and the specific state of the source code.

3.2. Dockerfile Configuration

We can also pass the commit hash as a build argument and set it as an environment variable within the Dockerfile:

FROM alpine
ARG GIT_COMMIT
ENV GIT_COMMIT=$GIT_COMMIT

4. Retrieving Commit Hash from a Running Container

Once the container is running, we can retrieve the commit hash using various methods. Let’s explore a few of them.

4.1. Using Docker Inspect

The docker inspect  command offers a comprehensive view of a container’s details, including its environment variables. This method is useful when we want to retrieve the commit hash without entering the container itself. Here’s an example command to achieve this:

$ docker inspect --format='{{.Config.Env}}' <container_id>

For example, we can use the command:

$ docker inspect --format='{{.Config.Env}}' my_container

This will produce the output:

[PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin GIT_COMMIT=ce85e2ebe299cf9a8237556c86dbcaaa2d571a3e]

4.2. Directly Accessing Environment Variables

If the build process sets the commit hash as an environment variable within the image, we can access it directly from the running container. This approach proves useful when we need the commit hash for scripting purposes inside the container. Here’s the command to retrieve an environment variable:

$ docker exec <container_id> printenv GIT_COMMIT

For example, we can apply this command:

$ docker exec my_container printenv GIT_COMMIT

The result of this command is:

ce85e2ebe299cf9a8237556c86dbcaaa2d571a3e

5. Automating the Process

To make the retrieval process seamless, consider automating these steps within our CI/CD pipeline.

Integrate the commit hash tagging and retrieval into our CI/CD pipeline to ensure consistency and automate verification steps:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Build Docker image
      run: docker build --build-arg GIT_COMMIT=${{ github.sha }} -t my_image:${{ github.sha }} .

6. Handling Errors

Sometimes, retrieving information from a stopped or non-existent container can result in errors. Ensure proper error handling in our scripts to manage such scenarios gracefully.

If we try to inspect a non-running container, we might encounter the following error:

Error: No such object: <container_id>

We should incorporate error handling in our scripts to manage such cases:

if ! docker inspect <container_id>; then
  echo "Container not found or not running"
fi

7. Conclusion

In this article, we’ve covered various methods to get the commit hash from a running Docker container.

By tagging our images with the commit hash and setting it as an environment variable, we can easily retrieve this critical information for debugging and verification purposes. Implementing these practices in our CI/CD pipeline ensures consistency and streamlines our development workflow.