One of the great things about Docker Hub is its automation tools. You can trigger a cascade of image creation from a single change in a base image.
But what happens if you want to trigger the creation of a whole set of images, all of them contained in a single repository and generated from a single Dockerfile? Well, we've got that covered too, in principle: using hooks.
As in the case of git hooks, they're a set of events triggered in different phases of the build process. Create a file with a certain name, put it in your repo's hook
directory, make it executable, and Bob's your uncle.
All examples I had seen, however, were written using shell scripts; for instance, this one. However, as soon as you need to create something with some complexity (processing JSON, for instance, or cough doing string comparisons) it starts to get really tiring. Mind you, shell scripts are incredibly powerful. But you can really save time using a real language.
It was not totally clear which languages were available, however. After a while (and some commands placed in hooks) I discovered, however, that it was an instance of Amazon Linux and that, indeed, there were a few languages available. Among them, Perl.
Initially I used Perl simply to extract tags. But then I realized I could use it for everything. So here's the resulting script
use strict;
use warnings;
use v5.14;
my $tags = `curl https://registry.hub.docker.com/v1/repositories/jjmerelo/alpine-raku/tags`;
my @tags = ($tags =~ /\"(2[^\"]+)\"/g );
for my $tag ( @tags ) {
say "👷 Building for $tag";
if ( $tag ge "2020.06" ) {
say "🚧 docker build hooks --build-arg CODE_VERSION=$tag -t jjmerelo/raku-test:$tag";
`docker build . -f hooks/Dockerfile --build-arg CODE_VERSION=$tag -t jjmerelo/raku-test:$tag`;
} else {
say "🚧 docker build -f hooks/root.Dockerfile --build-arg CODE_VERSION=$tag -t jjmerelo/raku-test:$tag";
`docker build . -f hooks/root.Dockerfile --build-arg CODE_VERSION=$tag -t jjmerelo/raku-test:$tag`;
}
`docker push jjmerelo/raku-test:$tag`;
}
What I needed was for the script to find out all tags in the alpine-raku
base image, and then build the corresponding test-raku
image with the same tag. The Dockerfile had been slightly tweaked to be able to use a base image that was defined, in part, by a command-line argument:
ARG CODE_VERSION
FROM jjmerelo/alpine-raku:${CODE_VERSION}
ARG CODE_VERSION
LABEL version="7.0.0" maintainer="JJ Merelo <jjmerelo@GMail.com>"
ARG DIR="/test"
USER root
# Set up dirs
RUN echo "Building from version ${CODE_VERSION}" && mkdir $DIR && chown raku $DIR
COPY --chown=raku test.sh /home/raku
VOLUME $DIR
WORKDIR $DIR
USER raku
# Will run this
ENTRYPOINT ["/home/raku/test.sh"]
ARG
needs to be repeated, since FROM
creates a new scope; that's only needed if you want to print something while building (which I might delete later).
Other than that, the script is relatively straightforward:
- Downloads the tags for the base image using the Docker Hub API. That gets all versions in a JSON, but I didn't want to install additional modules, so I just leverage the fact that all tags I'm interested with start with
2
and are between quotes to get that out of the JSON. - Then it's build/push time. The only thing here is that, prior to the
2020.07
version, I didn't use a non-privileged user for the image. So I needed to create two different Dockerfiles, one for each, which is why I need to find out what's the tag before choosing what to build. - Then it's build and push, with results already shown
It would be great if we had the full reference of things that can be used; for instance, having jq
installed would have saved me some trouble. Meanwhile, this pull request asks for adding, at least, some information on what's there so that we can build great hooks to automate the hell out of our docker image builds.
Top comments (0)