Challenge, Medium,  on  Containers

Use Docker Build Arguments to Inject Version and Commit Metadata into a Go Binary

A Go web server needs to be packaged into a container image with its version and commit hash baked in. The current Dockerfile compiles the app but the version metadata is missing. Your task is to find a way to inject the version metadata at build time.

Explore the application

The ~/app/ directory contains a Go web server and a basic Dockerfile. Take a moment to explore the code:

cat ~/app/main.go
cat ~/app/Dockerfile

Try building and running the image as-is:

docker build -t myapp:broken ~/app/
docker run -d -p 8080:8080 myapp:broken

The container starts fine, but the /api/info endpoint reports the version and commit as empty strings:

curl localhost:8080/api/info
{"commit":"","version":"","logFormat":"json",...}

The task

Modify the Dockerfile in ~/app/ so that the version and commit hash can be provided at build time and get embedded into the binary.

Then build the image as myapp:v1.2.0 with:

  • APP_VERSION = 1.2.0
  • COMMIT_HASH = abc1234

Modify the Dockerfile

Hint 1 - Why is the version metadata empty?

Look at the go build command in the Dockerfile - it already references ${APP_VERSION} and ${COMMIT_HASH} in the -ldflags. But where are these variables defined?

In a Dockerfile, variables used in RUN commands must be declared first. Check the Dockerfile reference to see which instruction declares build-time variables.

Hint 2 - Where to declare build arguments

Build arguments are scoped to the build stage where they are declared. In a multi-stage Dockerfile, declare them in the stage that actually needs the values - in this case, the stage where go build runs.

Build and test the image

Build the image with the required build arguments, then verify that the version metadata is correctly embedded:

Hint 3 - Passing values at build time

The docker build command accepts a --build-arg flag (one per variable) to supply values for ARG declarations in the Dockerfile.