Makefiles for your Dockerfiles

In this quick post, we will be adding a Makefile to ease our Docker commands...

After doing that, we would be able to:

Build the image if the Dockerfile change with:
make
Release for the registry stratus-clay:18078/jmkhael and version 1.2.3:
make release -e NS=stratus-clay:18078/jmkhael -e VERSION=1.2.3
Build a Raspberry Pi image (arm), with -arm appended to targets:
make build-arm

and support per user configurations too!

Let's go.

TLDR;

Clone https://github.com/jmkhael/make-for-docker and start from there, or just copy the Makefile and the make_env and customize them for your need.

Read the below for more information.

Per user configurations

Add a make_env to your repository, this will be the part that will change from a machine to another, between developers, CI...

Even empty will do. Here you are able to define a namespace (NS), ports (PORTS), volumes (VOLUMES), and environment variables (ENV) which will be passed to the docker run, build.. commands.

An example make_env file would look like:

NS=stratus-clay:18078/jmkhael
VOLUMES = -v /var/run/docker.sock=/var/run/docker.sock
PORTS = -p 5000:1234
ENV = \
  -e USER=jmkhael
  -e PASSWORD=******

Add this make_env file to your .gitignore or equivalent, in order not to commit this make_env (unless you want to impose that on everyone!)

Makefile template

Add a Makefile to your repository (like the below is a good start to build for a "default" architecture and an ARM one (Raspberry Pi). ARM images will have the prefix rpi (as per the conventions)

include make_env

NS ?= jmkhael
VERSION ?= latest

IMAGE_NAME ?= mx-fs
CONTAINER_NAME ?= mx-fs
CONTAINER_INSTANCE ?= default

.PHONY: build build-arm push push-arm shell shell-arm run run-arm start start-arm stop stop-arm rm rm-arm release release-arm

build: Dockerfile
    docker build -t $(NS)/$(IMAGE_NAME):$(VERSION) -f Dockerfile .

build-arm: Dockerfile.arm
    docker build -t $(NS)/rpi-$(IMAGE_NAME):$(VERSION) -f Dockerfile.arm .

push:
    docker push $(NS)/$(IMAGE_NAME):$(VERSION)
    
push-arm:
    docker push $(NS)/rpi-$(IMAGE_NAME):$(VERSION)

shell:
    docker run --rm --name $(CONTAINER_NAME)-$(CONTAINER_INSTANCE) -i -t $(PORTS) $(VOLUMES) $(ENV) $(NS)/$(IMAGE_NAME):$(VERSION) /bin/bash

shell-arm:
    docker run --rm --name rpi-$(CONTAINER_NAME)-$(CONTAINER_INSTANCE) -i -t $(PORTS) $(VOLUMES) $(ENV) $(NS)/rpi-$(IMAGE_NAME):$(VERSION) /bin/bash

run:
    docker run --rm --name $(CONTAINER_NAME)-$(CONTAINER_INSTANCE) $(PORTS) $(VOLUMES) $(ENV) $(NS)/$(IMAGE_NAME):$(VERSION)

run-arm:
    docker run --rm --name rpi-$(CONTAINER_NAME)-$(CONTAINER_INSTANCE) $(PORTS) $(VOLUMES) $(ENV) $(NS)/rpi-$(IMAGE_NAME):$(VERSION)

start:
    docker run -d --name $(CONTAINER_NAME)-$(CONTAINER_INSTANCE) $(PORTS) $(VOLUMES) $(ENV) $(NS)/$(IMAGE_NAME):$(VERSION)

start-arm:
    docker run -d --name rpi-$(CONTAINER_NAME)-$(CONTAINER_INSTANCE) $(PORTS) $(VOLUMES) $(ENV) $(NS)/rpi-$(IMAGE_NAME):$(VERSION)

stop:
    docker stop $(CONTAINER_NAME)-$(CONTAINER_INSTANCE)

stop-arm:
    docker stop rpi-$(CONTAINER_NAME)-$(CONTAINER_INSTANCE)

rm:
    docker rm $(CONTAINER_NAME)-$(CONTAINER_INSTANCE)

rm-arm:
    docker rm rpi-$(CONTAINER_NAME)-$(CONTAINER_INSTANCE)

release: build
    make push -e VERSION=$(VERSION)
    
release-arm: build-arm
    make push-arm -e VERSION=$(VERSION)

default: build

call make (optionally with -e to override some of the default variables defined in the makefile).

e.g. Release for the registry stratus-clay:18078/jmkhael and version 1.2.3

make release -e NS=stratus-clay:18078/jmkhael -e VERSION=1.2.3

e.g. Build for ARM, with -arm appended to targets:

make build-arm