<!--
  canonical-url: https://www.avonture.be/blog/makefile-using-make
  published:     2023-12-27
  This is a static plain-Markdown mirror generated at build time.
  Visit the canonical URL above for the fully rendered page, with images and interactive components.
-->

# Linux Makefile - When to use a makefile

> Stop memorizing complex Docker commands. Learn when and how to use a Linux makefile with GNU make to automate your project setup, logging, and environment management.

---
![Linux Makefile - When to use a makefile](/img/v2/makefile.webp)

**TL;DR**

This article makes the case for a project `makefile` (Linux/WSL only) as a single place to centralize otherwise-hard-to-remember commands — turning something like `docker compose up --detach` into `make up` — and shows a basic starter file with targets for common Docker actions, plus a tip on using `printf` to echo useful info (like credentials) when a target runs.

Coding your own `makefile` has the enormous, **terribly powerful advantage** of being able to centralize the commands you use on your project in a single place, whatever the nature of the project (php, javascript, nodeJs, markdown, etc.).

The presence of a file called `makefile` sends a clear message to anyone who comes to work on the project: *Hey, have a look here, you'll find all the commands you need*.

So, you can define an `up` command (you choose the name of the command) which will launch all the actions required to start the project; you could have `down` for just the opposite, `check` to check that the project is valid (e.g. launch static checks of the quality of your code, as in [Python - Code Quality tools](/blog/python-qa)), and so on.

## One word instead of that command

Here is a `make phpmyadmin` call, and just below it, the Docker command it stands for:

```bash
$ make phpmyadmin
User is root and password is example. Please open http://127.0.0.1:8089 to open phpmyadmin.

$ docker run --name phpmyadmin -d --link joomladb:db --network kingsbridge_default -p 8089:80 phpmyadmin
a0c37edd9f8c139556f1f0a6b028ec5102362f16233efbc05f56d184edfb83c9
```

One word on the left. A hundred and twenty characters of `--link`, `--network` and `-p` on the right — the kind of line nobody types from memory, and everybody ends up hunting for in their shell history.

And notice the second line of the output: the credentials and the URL are printed too, so you don't have to look them up either.

## What's inside the makefile

That whole behavior comes from a plain text file at the root of the project:

**makefile**

```
adminer:
  @printf "\e[1;033m%s\e[0m\n\n" "User is root and password is example. Please open http://127.0.0.1:8088?server=joomladb&username=root&db=joomla_db to open Adminer."
  @printf "\e[1;033m%s\e[0m\n\n" "Starting adminer. If the browser didn't open automatically, please surf to http://127.0.0.1:8088?server=joomladb&username=root&db=joomla_db to open adminer."
  docker run -d --rm --name adminer --link joomladb:db --network kingsbridge_default -p 8088:8080 adminer
  -sensible-browser http://localhost:8088 &

bash:
  @printf "\e[1;033m%s\e[0m\n\n" "Start an interactive shell in the Joomla Docker container; type exit to quit"
  docker compose exec joomla /bin/sh

code:
  code .

down:
  docker compose down

explorer:
  explorer.exe .

kill:
  docker compose kill

logs:
  docker compose logs --follow

start:
  @printf "\e[1;033m%s\e[0m\n\n" "Starting your website. If the browser didn't open automatically, please surf to http://127.0.0.1:8080 to open your site."
  -sensible-browser http://localhost:8080 &

up:
  docker compose up --detach

phpmyadmin:
  @printf "\e[1;033m%s\e[0m\n\n" "User is root and password is example. Please open http://127.0.0.1:8089 to open phpmyadmin."
  @printf "\e[1;033m%s\e[0m\n\n" "Starting phpmyadmin. If the browser didn't open automatically, please surf to http://127.0.0.1:8089 to open phpmyadmin."
  docker run --name phpmyadmin -d --link joomladb:db --network kingsbridge_default -p 8089:80 phpmyadmin
  -sensible-browser http://localhost:8089 &
```

Lines like `adminer:` or `bash:` are called `targets`; they are your commands. Take a look at the `up:` target: you'll retrieve one command and it's `docker compose up --detach`. So instead of remembering `docker compose up --detach` to run your application, you just run `make up`. To launch the browser and surf on your site, it will be `make start`.

The credentials shown above are printed by a `printf` call inside that target — a good habit for anything you'd otherwise have to look up.

> **Danger:**
>
> The indentation in a makefile **SHOULD BE** made using tabs and not spaces, this is crucial. So please make sure, if your file didn't work, you know what to do.

> **This file is specific to each project, not global.:**
>
> The `makefile`, being created in your project's directory, can contain instructions for that specific project. You could have one `makefile` for each project.

## Why bother

In the [Create your Joomla website using Docker](/blog/docker-joomla) blog article, we have seen a lot of docker commands.

By alphabetical order:

* `docker compose down`,
* `docker compose exec joomla /bin/sh`,
* `docker compose kill`,
* `docker compose logs --follow`,
* `docker compose up --detach`,
* `docker container list`,
* `docker image list`,
* `docker network list`,
* and many more

It's certainly not easy to remember them all — and it's much easier to remember a command like `make something` (and it can be anything, not just Docker).

**`make` is not installed yet?**

We use [GNU make](https://www.gnu.org/software/make/) for this.

First run `which make` in your Linux console to check if `make` is installed. If so, you will get f.i. `/usr/bin/make` as a result. If you got `make not found`, please run `sudo apt-get update && sudo apt-get -y install make` to install it.

The `makefile` itself is pure text so you can use any editor you want. On my side, I've now my own habits with Visual Studio Code. Make sure indentation is using tabs, not spaces.

> **Only for Linux / WSL (not for DOS/PowerShell):**
>
> This chapter only concerns Linux since DOS/PowerShell doesn't support the GNU make command.

## Conclusion

A `makefile` at the root of a project is a message to whoever opens it next — including yourself in six months: *everything you need to run this thing is here*. The commands stop living in your shell history and start living in the repository, versioned alongside the code they operate on.

The obvious next step is to make that list self-documenting: [Linux Makefile - Adding a help screen](/blog/makefile-help) shows how a bare `make` can print every available target with its description. And once you're convinced, [Makefile - Tutorial and Tips & Tricks](/blog/makefile_tips) collects everything I've learned since writing my first one.
