Multiple Docker Hub builds by parameterization

228 Views Asked by At

I have a requirement to build the same Dockerfile on a (relatively large) number of flavours.

In particular, I am working on a customization of Apache Tomcat. With the same Dockerfile, applying some enhancements to base Tomcat, I need to build several customized Tomcats based on different versions (n particular at least the baselines 8.5 and 9 combined with JDKs 8 and 11).

As an exercise only, just o get more practice on Docker, I could even decide to build all Tomcat images, which come in a large number of flavours, as customized builds.

Given that I already have a Dockerfile...

ARG TOMCAT_VERSION
FROM tomcat:${TOMCAT_VERSION}
MAINTAINER Some One ([email protected])
ARG POSTGRES_JDBC_VERSION="42.2.16"
ARG ORACLE_JDBC_VERSION="19.7.0.0"
ARG LIFECYCLE_LISTENER_VERSION="1.0.1"
ENV MAX_MEMORY_SIZE 4096
ARG CONTEXT_NAME

ADD https://repo1.maven.org/maven2/net/aschemann/tomcat/tomcat-lifecyclelistener/${LIFECYCLE_LISTENER_VERSION}/tomcat-lifecyclelistener-${LIFECYCLE_LISTENER_VERSION}.jar /usr/local/tomcat/lib
ADD https://repo1.maven.org/maven2/org/postgresql/postgresql/${POSTGRES_JDBC_VERSION}/postgresql-${POSTGRES_JDBC_VERSION}.jar /usr/local/tomcat/lib
ADD https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc8/${ORACLE_JDBC_VERSION}/ojdbc8-${ORACLE_JDBC_VERSION}.jar /usr/local/tomcat/lib
COPY tomcat-${TOMCAT_MAJOR}/server.xml /usr/local/tomcat/conf/ #This enables AJP

EXPOSE 8009
EXPOSE 8080

VOLUME #some volume
# etc etc

What I need to achieve is, possibly using Docker Hub's auto-build is

for (tomcatVersion in "8.5", "9")
    for (javaVersion in "jd8-slim", "jdk11-slim", "jdk14")
        docker build --build-arg TOMCAT_VERSION=$tomcatVersion+"-"+$javaVersion -t examplebiz/tomcat:$tomcatVersion+"-"+$javaVersion .

Currently Docker Hub offers to me use multiple Github branches

Docker Hub Build Settings

But I don't like this, as a single Dockerfile is sufficient. I can combine the 6 versions and run the build manually from my pc

I haven't very well understood the build hooks. Maybe there lies the solution?

Can I get some advice on how to design the build?

2

There are 2 best solutions below

0
On BEST ANSWER

In addition to BMitch's answer, I also found my own way in the meantime and I'd like to share my experience, possibly explaining.

Docker Hub allows hooks automation. In particular, the build hook, as described in the docs, will override the entire build process. One can choose whether to change the variables passed to Docker, or to reinvent brand new ways of building!!

I just had to translate my pseudo-code for cycle into a real bash for cycle

#!/bin/bash

for tomcatVersion in "8.5" "9" ; do
    for javaVersion in "jdk8-slim" "jdk11-slim" "jdk14" ; do
        imageVersion="$tomcatVersion-$javaVersion"
        echo "Building Tomcat $imageVersion"
        docker build --build-arg TOMCAT_VERSION=$imageVersion -t examplebiz/tomcat:$imageVersion .;
        docker push examplebiz/tomcat:$imageVersion
    done
done

docker tag examplebiz/tomcat:$imageVersion examplebiz/tomcat:latest

There are just two caveats:

  1. Docker Hub won't ever push anything by itself. Whatever custom you build, you must push it. That is why I have the docker push line and I use the last value of the variable imageVersion in my code

  2. Docker Hub will push a repository:latest image after the build, so it demands its presence. Make your choice on who to promote latest, but make sure Docker has built a latest image, whether with a tag or a plain build

0
On

The functionality from Docker Hub builds doesn't have a lot of options. If you need more configurability and are hosting your project in GitHub, have a look at GitHub Actions instead.

Docker has a build-push action that has lots of options. And to support the multiple options, the matrix syntax in GitHub actions allows you to run multiple builds with different settings. What you're left with looks like a file call .github/workflows/docker.yml in your project (docker can be renamed) with:

name: docker

on:
  push:
    branches: master

jobs:
  docker:
    strategy:
      matrix:
        tomcatVer: ["8.5", "9"]
        javaVer: ["jd8-slim", "jdk11-slim", "jdk14"]
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2
      - name: Login to DockerHub
        uses: docker/login-action@v1 
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          push: true
          tags: examplebiz/tomcat:${{ matrix.tomcatVer }}-${{ matrix.javaVer }}
          build-args: |
            TOMCAT_VERSION=${{ matrix.tomcatVer }}-${{ matrix.javaVer }}