In a Continuous Delivery pipeline, we like to ensure that every docker image refers to a specific git commit. With this reusable Makefile we ensure that each tag will have a semantic version and point to the exact commit in git at the same time! Based upon the current state of your git workspace it will generate a docker image with:
- a clean tag ‘1.0.0’ if the workspace exactly matches the tagged commit.
- a tag with release and commit hash ‘1.0.0-hash’ if the workspace has changed since the tag.
- a tag ‘1.0.0-hash-dirty’ if the workspace has outstanding changes.
You can use this Makefile as a base and reuse it for any of your Docker projects.
Makefile targets
The Makefile has the following targets:
make showver will show the current release tag based on the directory content.
make build builds a new version of your Docker image and tags it
make snapshot build from the current (dirty) workspace and pushes the image to the registry
make release build the current release and push the image to the registry
make patch-release increments the patch release level, build and push to registry
make minor-release increments the minor release level, build and push to registry
make major-release increments the major release level, build and push to registry
make tag-patch-release increments the patch release level, without build and push to registry
make tag-minor-release increments the minor release level, without build and push to registry
make tag-major-release increments the major release level, without build and push to registry
make check-status will check whether there are outstanding changes
make check-release will check whether the current directory matches the tagged release in git.
How to use it.
copy the Makefile and .make-release-support into your Docker git project:
wget https://raw.githubusercontent.com/mvanholsteijn/docker-makefile/master/Makefile
wget https://raw.githubusercontent.com/mvanholsteijn/docker-makefile/master/.make-release-support
Change registry, user or image name
By default, the registry is set to docker.io and the user to the current user and the name of the image
to the name of the current directory. To override this, edit the Makefile
and set the variables REGISTRY_HOST
, USERNAME
and NAME
.
REGISTRY_HOST=myregistry.io
USERNAME=mvanholsteijn
NAME=awesome-image
Building an image
to build an image, add a Dockerfile to your directory and type:
make build
When you would like to push the image based on the current workspace to the repository, use:
make snapshot
this will build the image and push it to the repository with the current tag. A good command to run on your continuous integration server, as it will create images with individual tags on each commit.
Release
To make a release and tag it, commit the changes and type:
make patch-release
This will bump the patch-release number, build the image and push it to the registry. It will only
release if there are no outstanding changes and the content of the directory equals the tagged content. Alternatively you can choose ‘make minor-release’ or ‘make major-release’ to bump the associated number.
Release number
The release of your docker image is kept in the file .release and uses the following format:
release=<major>.<minor>.<patch>
The name of the git tag is kept in the same file, and by default will have the format:
tag=<directory-name>-<major>.<minor>.<patch>
This will allow you to have track and tag multiple images in a single Git repository. If you want to use a different tag prefix, change it in the .release.
Image name and tag
The name of the image will be created as follows:
<registry-host>/<username>/<directory-name>:<tag>
The tag is has the following format:
format | when |
---|---|
workspace is equal to tagged content in git | |
– | workspace is not equal to the tagged content |
–dirty | workspace has uncommitted changes |
Multiple docker images in a single git repository.
If you want to maintain multiple docker images in a single git repository, you can use an alternate setup where the Makefile is located in a silbing directory.
├── multiple-example
│ ├── ...
│ ├── image1
│ │ ├── .release
│ │ ├── Dockerfile
│ │ └── Makefile
│ ├── image2
│ │ ├── .release
│ │ ├── Dockerfile
│ │ └── Makefile
│ └── make
│ ├── .make-release-support
│ ├── Makefile
The Makefile in the image directories will include the generic Makefile. In this Makefile you can alter the names and tailor the build by adding pre and post build targets. Checkout the directory (multiple-example) for an example.
Create the generic make directory
To create the generic make directory, type:
mkdir make
cd make
wget https://raw.githubusercontent.com/mvanholsteijn/docker-makefile/master/Makefile
wget https://raw.githubusercontent.com/mvanholsteijn/docker-makefile/master/.make-release-support
Create docker image directory
For each docker images, you create a sibling directory:
mkdir ../image1
cd ../image1
cat > Makefile <<!
include ../make/Makefile
USERNAME=mvanholsteijn
pre-build:
@echo do some stuff before the docker build
post-build:
@echo do some stuff after the docker build
!
Now you can use the make build and release instructions to build these images.
pre tag command
If you want add the current release to a source file, you can add the property pre_tag_command
to the .release file.
this command is executed when the .release file is updated and before the tag is placed. In the command @@RELEASE@@ is
replaced with the current release before it is executed. For example:
release=0.1.0
tag=v0.1.0
pre_tag_command=sed -i "" -e 's/^version=.*/version="@@RELEASE@@"/' setup.py
Conclusion
This reusable makefile makes it very easy for you to start building docker images with tags that reflect the state of the git workspace it was build on. Try it, and let
me know if it made your life easier!