If you manage multiple docker images on docker hub, you want to make the support the easiest possible. But most of the time you start creating tags because your application follow the version of another application or you just want to try using the new debian image.

To create tag, docker hub provides you the Build settings page where you can declare tags, giving you 2 options:

  • use branch (Docker hub does it automatically, but you can do more specific stuff with it)
  • use different Dockerfile files Both are not perfect because branches need to be merge and multiple dockerfile results in duplicate code most of the time.

If yours tags are quite similar (base image or one RUN different) you have a better option using build args. Build arg are like environment variables but used during the build. You can specify them with docker build –build-arg = or in docker cloud at a global scope (Docker Cloud Automated Build). They can be use in most of the directives present in Dockerfile; for example you can change the base image, change RUN instruction using if/else

But how to use it with tag: start to rewrite yours dockerfiles according to differences between tags adding build args.

ARG  BASE_IMAGE=stable
FROM debian:${BASE_IMAGE}

ARG PHPVERSION=5
ARG PHPCONF=/etc/php/5

RUN echo $PHPVERSION $PHPCONF && \
	cat /etc/debian_version && \
	[ "$PHPVERSION" != "5" ] || echo "specific for version 5" && \
	echo "global setup"

There are 3 builds args defining my docker image and if I want to build different tags I just have to pick the right build parameters.

But on Docker Hub you don’t have this feature, so you can use the phase hooks. Hooks are script executed at specific moment during the build (pre push for example) and one of the hook is call build and replace the standard build command used. It allows you to write your own logic, define all the build arguments you want. (You will always need to create tags in Docker hub)

#!/usr/bin/env bash

LATEST_VERSION="5"

if [ "$DOCKER_TAG" = "$LATEST_VERSION" ]; then
	DOCKER_TAG=latest
fi

if [ "$DOCKER_TAG" = "latest" ]; then
	docker build -t ${IMAGE_NAME} .
else
	if [ -f "Dockerfile.${DOCKER_TAG}" ]; then
		docker build -t ${IMAGE_NAME} -f Dockerfile.${DOCKER_TAG} .
	else
		if [ "$DOCKER_TAG" = "6" ]; then
			docker build -t ${IMAGE_NAME} \
				--build-arg=BASE_IMAGE=stretch \
				--build-arg=PHPVERSION=7 \
				--build-arg=PHPCONF=/etc/php/7.0 \
				.
		fi
	fi
fi

In this hooks/build file, $DOCKER_TAG is setup with values of the Build settings page. The latest tag is define here as the version 5. Some tags use specific Dockerfile files. Version 6 use the same Dockerfile than version 5, but with a stretch base image and others different build arguments. You can do what you want, it’s a bash script (do not build more than one, it will not work).

At the end, my Build Settings doesn’t specify branches or different dockerfile but I have at the end 4 different tags.

The github repository of this example: nouchka/docker-hubtest. This was inspired by a feature request on Docker Hub Github.