Exercise 4: Use git tags to create a named version of a docker image

Objective

Use git tags to create automatically labelled versions of docker images.

See how to use git tags to add extra steps to the CI/CD pipeline, for more detailed testing and verification of your code.

Using the git tag to tag the docker image

Gitlab directly supports specifying that certain stages will run only for git branches other than the ‘master’ branch, or only if the code has been tagged with ‘git tag’. By using a combination of YAML directives and the environment variables that gitlab provides to the build, you can build a docker image which is tagged with the same name as your git tag or branch.

Once the .gitlab-ci.yml file has been correctly set up, creating a tagged docker image is as simple as this:

git tag v1.0
git push --tags

While you’re waiting for the build to complete, inspect the .gitlab-ci.yml file to see how it uses the tag. There are a few places where the magic happens:

  • the variables section defines two variables: RELEASE_IMAGE and LATEST_IMAGE, differing only in that one uses the CI_BUILD_REF_NAME environment variable, the other hardwires the name latest
  • the before_script stanza sets DOCKER_IMAGE to one or the other of these variables, depending on the value of CI_BUILD_REF_NAME. For the master branch, CI_BUILD_REF_NAME will be master, this bit of code effectively changes that to latest instead.
  • in the install step, the DOCKER_IMAGE variable is used to actually tag the image that’s pushed to the registry

Most of the complication there comes from the fact that the default branch name in git is master, while the default tag name in docker is latest. We could remove the before_script part and just use the RELEASE_IMAGE variable everywhere, but then we’d end up with docker images tagged master, which isn’t nice.

Using the git tag to control the build

If you look at the CICD -> Pipelines page after your tagged build has completed, you’ll see it has three steps to it. There is a run step that executes the test stage, this isn’t executed unless the code has been tagged in git. The only: directive in the .gitlab-ci.yml file controls that behaviour.

Since you are likely to commit code much more often than you are to tag it, you can see how this can be used to test tagged code in-depth, in ways that might be wasteful of resources if you tested every single commit to the same level.

Check your Registry to see the named docker image

Once the build completes, go to your Registry page again, and click on your project link at the top-left to see what images you have. You now have a latest and a v1.0 version of your docker image. Check you can run that tagged version from the command line:

> docker run registry.gitlab.com/tonywildish/tiny-test:v1.0
Unable to find image 'registry.gitlab.com/tonywildish/tiny-test:v1.0' locally
v1.0: Pulling from tonywildish/tiny-test
7413c47ba209: Already exists 
0fe7e7cbb2e8: Already exists 
1d425c982345: Already exists 
344da5c95cec: Already exists 
69e5cbbf5881: Pull complete 
737987b4e0ef: Pull complete 
Digest: sha256:e1445aff15c845b2f795fc49f8b2bcb41f34cd4a6a3c3eef98bb61bea26a986b
Status: Downloaded newer image for registry.gitlab.com/tonywildish/tiny-test:v1.0
Hello World
Compiled on Tue Jul 30 10:58:09 UTC 2019

Bonus exercise: git branches

What happens if you use a git branch, instead of a tag? The CI/CD pipeline will still fire, and will know the branch name, so it uses that in the docker image tag. However, since your .gitlab-ci.yml file only runs the test stage for git tags and not for git branches, you will only get a two-stage pipeline.

Can you modify the YAML file so it runs for branches too? Check the documentation for help.

If you’re on a branch, and you use a tag too, what do you think gitlab will do? Try it and find out.

Conclusion

You now know how to control the activities in a build when using git tags, and how to use those tags to automatically tag the docker image with the same name.

Best Practices

  • Use git tags to define important versions of your code.
  • Use the only: directive in your builds to make sure that tagged code is tested thoroughly.