DEV Community

Gerard Rico Botella
Gerard Rico Botella

Posted on

How to manage docker-compose Symfony project using Make

In my previous post I explained how to setup docker-compose for a symfony project. Manage docker-compose projects can be anoying if we use docker/docker-compose commands for it. With Make, we can manage it in a simpler way.

What is Make?

According to the make page from GNU project website:

GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.

Make gets its knowledge of how to build your program from a file called the makefile, which lists each of the non-source files and how to compute it from other files. When you write a program, you should write a makefile for it, so that it is possible to use Make to build and install the program.

A good place to learn how to use Makefiles is makefiletutorial website

How would we use Make?

As you can see in its definition, it's main pourpose is to generate files from source code, but we will use it to simplificate execution of the commands needed to manage a docker-compose symfony project.

Make's targets allows us to create aliases to other commands. For example, to run a symfony command in your container you will run something like:

docker exec -it bin/console your:command

If you need to run this command often, this could become anoying. With make, we can define the following target:

console/%
    docker exec -it bin/console $*
Enter fullscreen mode Exit fullscreen mode

To use this target you simply run

make console/your:comand

That is pretty much simpler than docker's full command.

Creating our Makefile

Firs of all, we create a file name Makefile in our project root directory.

Docker related targets

The first target we are going to create is to execute docker-compose commands:

docker-compose/%:
    @USER=${USER} docker-compose $*
Enter fullscreen mode Exit fullscreen mode

USER=${USER} is to tell docker-compose which user we want to use inside the container. This is needed to prevent permissions errors between host and container generated files.
To make it work, we will add the following variable at the begining of our Makefile:

USER := $(shell id -u):$(shell id -g)
Enter fullscreen mode Exit fullscreen mode

With this, we are setting the user:group of our user to the USER variable.

Finally, we need to add user option to our service configuration (in docker-composer.yml) and set it to the environment variable $USER:

example_php:
    container_name: example_php
    user: $USER
    build:
      context: .
    working_dir: /var/www/app/
    volumes:
      - './:/var/www/app/'
Enter fullscreen mode Exit fullscreen mode

Helper targets

To keep things simple on our daily usage, we will add the following helper targets:

  • up: Build and start services
  • start: Start services
  • stop: Stop services
  • build: Build or rebuild services
  • exec: Execute commands inside PHP service
  • bash: Execute bash inside our PHP service
up:
    @make docker-compose/"up -d"

start:
    @make docker-compose/"start"

stop:
    @make docker-compose/"stop"

build:
    @make docker-compose/build

exec/%:
    @docker exec -it ${PHP_CONTAINER} $*

bash:
    @make exec/bash
Enter fullscreen mode Exit fullscreen mode

Other targets

Given the previously defined docker targets, it's easy to add targets. For example, we can add a symfony console target to run console commands:

console/%:
    @make exec/"bin/console $*"
Enter fullscreen mode Exit fullscreen mode

As you can see, we use the exec target previously defined.
We can add all targets that we could need using this format.

All together

# ----------------------------------------------------------------------------
# Configuration
# ----------------------------------------------------------------------------

USER := $(shell id -u):$(shell id -g)
NGINX_CONTAINER = "example_nginx"
PHP_CONTAINER = "example_php"

# ----------------------------------------------------------------------------
# Docker
# ----------------------------------------------------------------------------

docker-compose/%:
    @USER=${USER} docker-compose $*

up:
    @make docker-compose/"up -d"

build:
    @make docker-compose/build

exec/%:
    @docker exec -it ${PHP_CONTAINER} $*

bash:
    @make exec/bash

# ----------------------------------------------------------------------------
# Composer
# ----------------------------------------------------------------------------

composer/%:
    @make exec/"composer $*"

composer-install:
    @make composer/"install"

composer-require/%:
    @make composer/"require $*"

composer-require-dev/%:
    @make composer/"require --dev $*"

# ----------------------------------------------------------------------------
# Symfony
# ----------------------------------------------------------------------------

console/%:
    @make exec/"bin/console $*"

# ----------------------------------------------------------------------------
# Tests
# ----------------------------------------------------------------------------

phpunit/%:
    @make exec/"vendor/bin/phpunit -c phpunit.xml.dist $*"

test:
    @make phpunit/" "

test/%:
    @make phpunit/"--testsuite $*"
Enter fullscreen mode Exit fullscreen mode

How to use it

Set up

If you don't have built your services yet, run make up.
If services are already built, run make up

Dependencies

Run make composer-install to install all dependencies.

Run make composer-require/example/package to require packages. For example, to install ramsey/uuid, you will run make composer-require/ramsey/uuid.

Symfony commands

You can run any symfony command running make console/your:command. For example, if you need to clear cache, you will run make console/cache:clear. You can pass arguments and options wrapping command into double quotes: make console/cache:clear -e prod.

Tests

To run all suites, run make test.
If you want to run only your unit test suite, run make test/unit

Top comments (0)