DEV Community

Cover image for Writing Docker Hub hooks in Perl
Juan Julián Merelo Guervós
Juan Julián Merelo Guervós

Posted on

Writing Docker Hub hooks in Perl

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.
Showing output of the hook, with 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`;
}
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode

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)