Using Makefiles to build and publish (docker) containers
Tags: docker
Published: 2020-08-25 08:21:34

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ian08d74e3n2c901wji8.png)

*There are more things in make and dockerfiles, Horatio,
Than are explained of in your documentation.*


## Intro
First of all, let's start this brief train of thought by acknowledging that despite docker is a synonym of containers, the other way around isn't true.

We could dwell on the origins of containers, but there are tons of much more valid articles out there than anything I could begin to try to explain here. 

I'm assuming that containers, docker and dockerfiles aren't new terms for anyone reading this, but if that's the case then you can probably start by checking [containers](https://www.ibm.com/cloud/learn/containers), [docker](https://www.docker.com/) and [dockerfile].(https://docs.docker.com/engine/reference/builder/)

## Motivation
Usually, when I'm writing a *dockerfile* to ensure I'll never forget the needed steps to successfully build this or that container I always find myself looking at all those _hardcoded_ version numbers and other things that could really fit in the definition of variables but for some reason end up for (commit&push) posterity.

By now you must be thinking, using some nice words, that **_this guy should really learn how to work with docker build arguments and stop wasting my time_**, but there is no denying it always ends up on memorizing all the arguments, which never happens.

## Dockerfile

### First step: meet [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
What kubectl is or does is out of scope for this post. We're only using it out as an example, because it was the first thing that popped into my mind.
Let's build a small container for kubectl:
```
FROM alpine:3.12

ADD https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl /usr/local/bin/kubectl

RUN chmod +x /usr/local/bin/kubectl

ENTRYPOINT ["kubectl"]
```

As you can see, in just a small dockerfile, 2 hardcoded versions just jump into eyesight:
* the alpine version itself
* the kubectl version

### Second step: some adjustments
Luckily Dockerfile syntax (evolving or not through the years) allows us to do some nice modifications:
```
ARG ALP_VER=3.12
FROM alpine:$ALP_VER

ARG KCTL_VER=1.18.0

ADD https://storage.googleapis.com/kubernetes-release/release/v${KCTL_VER}/bin/linux/amd64/kubectl /usr/local/bin/kubectl

RUN chmod +x /usr/local/bin/kubectl

ENTRYPOINT ["kubectl"]
```
So now, not only I can modify those two versions as I please, as I can build the image without passing any argument (which will build it with the default versions).

Of course I could just go and issue a docker build command that simply works with that Dockerfile and shows how I can manipulate those arguments 
`docker build --build-arg ALP_VER=3.11 --build-arg KCTL_VER=1.18.0 -t my_kubectl:1.18.0 .`.

But that just wasn't enough for me. It's not that hard, but then I'd have to remember the argument names for several dockerfiles.

## The Makefile
I decided I'd only settle for a simpler syntax. 
Not only something that didn't make me type those long commands but at the same time, something a little nicer than a simple (and ugly) bash script.

{% gist https://gist.github.com/flpslv/b3a6bc79c1682de11a45b347782c969f %}

Now I can just build using whatever versions I want:
* default `make build`
* another alpine version `make build alpver=3.11`
* another kubectl version `make build kctlver=1.17.0`
* both modified versions `make build alpver=3.11 kctlver=1.17.0`

I can build and push into the configured registry
* default `make`
* another alpine version `make alpver=3.11`
* ... and so on ...

Or I can easily check ( without any file opening ) which things I can change on that image
* `make help`

Surely there are other things that got hardcoded somewhere, like the repository name, but this is only the beginning.

Of course this isn't THE WAY nor THE ONLY WAY. I'm not that naive. I'm sure many other options are available to do it and I'd like to know about them in the comment area.