Make is a fantastic open source utility that can be used to chain commands together to accomplish things like building or deploying your code. If you are familiar with using NPM in the JavaScript ecosystem to chain commands together using package.json, Make is very similar but is framework agnostic.

Install Make

Make is the name of the binary that needs to be installed to process makefiles. Installing the binary differs depending on your setup. If you are using a Mac, you can use Homebrew to install Make with the command below:

brew install make

For Windows, you’ll want to use the Windows Subsystem for Linux and install it in that environment. Ubuntu is the WSL environment I used to use, so in there I’d be able to run the following:

sudo apt update
sudo apt install make

For further details on installing and using WSL, refer to Microsofts docs.

Your first makefile

Makefiles are simply named as makefile with no extension. Essentially they run bash commands, so for the first example will contain the following and it will simply write a command that will echo hello world into the terminal.

hello:
	echo "hello world"

Now to run commands from makefiles, you run make {command} so to run the example above you’d type make hello and “hello world” should be shown in the terminal.

Using variables

Variables in makefiles can be used to simplify what you have to type over and over. We can update the above example like so to echo out “hello Brian” when make hello is run:

NAME=Brian

hello:
	echo "hello ${NAME}"

Chain commands

You can also chain commands together, so let’s create a command called greet that first call the hello command before it runs the script defined in its own command. Notice how on the line with greet: I’m putting hello next to it, which tells make to run hello before greet.

NAME=Brian

hello:
	echo "hello ${NAME}"

greet: hello # this tells make to run `hello` first
	echo "how are you?"

Using for Docker development

Now lets look at a few use cases that can help simplify your Docker development environment.

Build an image

Let’s say were working with a container named hello-world:latest and we want to build this. Typically the command to build an image for this would be:

docker build . -t hello-world:latest

Not terrible to run every time, but we can simplify this with the following makefile to run make build each time instead:

IMAGE=hello-world
TAG=latest

build:
	docker build . -t "${IMAGE}:${TAG}"

Run an image

Building an image is a one line command anyways, but if you want to consistently run the latest version of your image, you’d have to build first, then run it. NOW we can see the power of make where we chain a build and run command into a single execution of make run from the terminal:

IMAGE=hello-world
TAG=latest

build:
	docker build . -t "${IMAGE}:${TAG}"

run: build
	docker run "${IMAGE}:${TAG}"

Publish an image

We can apply the same logic as above to build and publish the image when its ready to go. Given the following makefile, you can use make publish to deploy your image to Dockerhub (my username is brianmm02).

IMAGE=hello-world
TAG=latest

build:
	docker build . -t "${IMAGE}:${TAG}"

run: build
	docker run "${IMAGE}:${TAG}"

publish: build
	docker push "brianmm02/${IMAGE}:${TAG}"