How to properly use Makefiles in web development

GNU Make has been used for years in software development, making handling large codebases and sources easier for developers.

It’s now time for it to make its way to web development.

In this article, we’ll cover how it can help with Docker-based environments, as the developers often use the same commands over and over, for example generating migrations, rebuilding the database, clearing the cache…

If you’re working on a Symfony project, you need to use bin/console quite often, since all the commands that you will create and all the framework’s commands are used through this console.

When working with Docker, to access the container’s filesystem you have two choices: docker-compose exec|run <service name> bash|sh then enter the command you want to run…
… or create a Make recipe to make this faster!
From now on, our main service will be named server.

bash:
docker-compose exec server bash

Now we can use make bash to connect to the container’s CLI, which will save time every time we’ll need to execute something inside.

Let’s now enhance this Makefile and add a recipe to handle the database.

DKCE = docker-compose execbash:
$(DKCE) server bash
_create-database:
bin/console doctrine:database:create
_drop-database:
bin/console doctrine:database:drop --force
_migrate:
bin/console doctrine:migrations:migrate
_load-fixtures:
bin/console doctrine:fixtures:load
_reload-database: _drop-database
_reload-database: _create-database
_reload-database: _migrate
_reload-database: _load-fixtures
reload-database:
$(DKCE) server exec bash -c "make _reload-database"

Here we created four recipes that are meant to be executed in the container.
I’m using underscores as the first character to make it more obvious and easier to read later.

I then chain these recipes into a bigger one: _reload-database, which I execute in the container from the outside by passing the command I want to run as the -c argument of the bash command in the reload-database recipe.

That’s it! We can go a bit further and add more complexity to our commands, include environment variables in the recipes by calling include .env at the beginning of the file and use them with $(VARIABLE_NAME).

Another example of a great usage can be installing the dependencies of a project:

_vendor:
composer install --optimize-autolader
vendor:
$(DKCE) server bash -c "make _vendor"

The use-cases are endless!

I often create an install recipe that included everything I need to start my project from a fresh git clone.

To have an example of a Makefile that contains numerous useful recipes, visit my Symfony-Docker starter template.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Edouard Courty

Edouard Courty

Digital Transformation Masters Degree & IT Teacher @IIMparis Back-end fanatic & Symfony lover. Co-founder of @IMXrarity