Configuring a Laravel application with Docker Compose for local development using RabbitMq, MariaDB, and Redis

Welcome to the eighth post of the blog. We will set up and run a Laravel application (PHP) Repository:

PHPUsed as Backend7.4.11
NginxUsed as Webserver1.19.3
MariaDBUsed as SQL database10.5.6-MariaDB
RedisUsed as Cache Storage6.0.8
RabbitMqUsed as message broker3.8.9


Have the following dependencies previously installed and configured:

  • Docker
  • Docker Compose

Composition of Services

Specifications of application services.

ServiceDescriptionService dependencies
phpDomain of the API backend application exposed with PHP FPM.mysql, redis, rabbitmq
worker-phpDomain of the application for execution of routines.mysql
Domain of the application for consumption of the message broker.
mysql, rabbitmq
webResource responsible for the application’s web server with assembly for configuration.php
rabbitmqResource responsible for messaging and providing the graphical interface.
mysqlResource responsible for the SQL database persisted in a host local disk
Example of docker-compose.yml file


Understanding the service configuration: php

php: # Service name
    build: # Start build session
      context: .  # Level where the build should be executed
      dockerfile: ./docker/php7-fpm/Dockerfile # Dockerfile chosen (default file with name Dockerfile, on the same level as the docker-compose file)
    image: repo-registry-local/libraryapitest-app-example:v4.0 # image that will be used as a base for the build. can also be used to be sent to the registry, like this example
    container_name: php-library-example # container name when uploading the service
    depends_on: # depends on other services, will start only when the list below is up
      - redis
      - mysql
      - rabbitmq
    command: bash -c "php artisan migrate && php-fpm" # Dockerfile CMD attribute overlap
    env_file: # environment variables coming from a file
      - docker/docker-compose-env/application.env
    environment: # explicit environment variables, can also be used to overwrite variables
      APP_NAME: 'Overlaying - Library API
    links: # When listed, the container passes and see the services below
      - mysql
      - redis
      - rabbitmq
    volumes: # External mounting area
     - ./application/:/app:rw
     - /app/vendor

Application topology

Starting the application

now that we have a basic understanding of the app’s features, let’s get started.

docker-compose up -d

The above command executes all the services contained in our docker-compose to start, with the following result.

Starting redis-library ... done
Starting mysql-library ... done
Starting rabbitmq                   ... done
Starting php-library-example-worker ... done
Starting php-library-example              ... done
Starting php-library-worker-queue-example ... done
Starting nginx-library                    ... done

It is also possible to break down the services we want to start with the command below.

docker-compose up rabbitmq mysql -d

Or perform the build of all services or a particular service as we can see below.

docker-compose build
docker-compose build php

Checking Services

We can verify that the services started correctly with the following command :

docker ps

With the following result:

2f0d029513c3 nginx:1.19-alpine "/docker-entrypoint.…" 3 days ago Up 18 minutes>80/tcp nginx-library
90a5a7a0d335 repo-registry-local/libraryapitest-app-example:v4.0 "docker-php-entrypoi…" 3 days ago Up 18 minutes 9000/tcp php-library-example
9630371843b4 libraryapiotra:php-worker-example "docker-php-entrypoi…" 3 days ago Up 18 minutes 9000/tcp php-library-example-worker
71861ab99b26 libraryapiotra:php-worker-queue "docker-php-entrypoi…" 3 days ago Up 18 minutes 9000/tcp php-library-worker-queue-example
9fcb27caaceb mariadb:latest "docker-entrypoint.s…" 13 days ago Up 19 minutes>3306/tcp mysql-library
40f05238ace7 rabbitmq:3-management-alpine "docker-entrypoint.s…" 13 days ago Up 18 minutes 4369/tcp, 5671/tcp,>5672/tcp, 15671/tcp, 15691-15692/tcp, 25672/tcp,>15672/tcp rabbitmq
e85dbe64c2e6 redis:alpine "docker-entrypoint.s…" 13 days ago Up 18 minutes 6379/tcp redis-library

Viewing API (Swagger) documentation

When starting our application, we can see the API documentation from the following address:


Understanding interdependencies

We will use some routes to better understand the participation of different services among themselves, for this, we will see 3 use cases:



The purpose of this resource is to present the detailing of a book, using the Cache resource to avoid the use of an SQL database for example, during the time that Cache exists, or that there is a change in the data, moments in which the index is invalidated.

UML route representation: GET book/{bookId}

Application representation for the route: GET book/{bookId}

When you click on Try it out >> fill in the Book Id field >> click on Execute.

In this route we used a Cache for consultation, using the Driver that sends to Redis, as we can see below, three books were viewed: book 13, 15, and 16, and we have the value of the index generated in our Redis instant.


The purpose of this feature is to send a message to our Message Broker so that it can be processed at another time asynchronously.

UML route representation: POST /author/process/message

Route application representation: POST /author/process/message

After clicking Try it out >> fill in the message field >> click on Execute.

We will receive a message that our message will be processed. this message only and generated, if our Message Broker received and accepted our message.

Accessing The Message Broker:

Login: admin
Password: admin

Checking Messages received on:

We can notice that we have 4 messages waiting for processing. in the queue called test, which was configured in our Laravel application.

When clicking on the Messages menu:

We can see more details of the message, and how Laravel sends it to be processed by default.
{"displayName":"App\\Jobs\\ProcessExperimentalJob","job":"Illuminate\\Queue\\CallQueuedHandler@call","maxTries":null,"timeout":null,"timeoutAt":null,"data":{"commandName":"App\\Jobs\\ProcessExperimentalJob","command":"O:31:\"App\\Jobs\\ProcessExperimentalJob\":8:{s:40:\"\u0000App\\Jobs\\ProcessExperimentalJob\u0000message\";s:87:\"Place the message here for the processing queue received at: 2021-01-30 22:51:54:507117\";s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:5:\"delay\";N;s:7:\"chained\";a:0:{}}"},"id":"bLVXYvR1U9wzTXtGJNQEiLl2wkx8Zqtl"}

Example of a payload message sent by our application.


The purpose of this feature is to process a message from our Message Broker, we can see its processing as well as its completion in our queue.

UML representation of queue processing

Representation of the application on queue processing

      context: .
      dockerfile: ./docker/php7-fpm/Dockerfile
    image: libraryapiotra:php-worker-queue
    container_name: php-library-worker-queue-example
      - mysql
      - rabbitmq
    command: sh -c "php /app/artisan queue:work --verbose --tries=7 --timeout=90"
      - docker/docker-compose-env/application.env
      APP_NAME: 'Queue Worker - Library API'
      - mysql
      - redis
      - rabbitmq
      - ./application/:/app:rw

Execução do serviço:

php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30a841676.51726260] Processing: App\Jobs\ProcessExperimentalJob
php-library-worker-queue-example | {"message":"Place the message here for the processing queue received at: 2021-01-30 22:51:54:507117 Processed on: 2021-01-31 00:47:38:247462","context":[],"level":200,"level_name":"INFO","channel":"local","datetime":{"date":"2021-01-31 00:47:38.249261","timezone_type":3,"timezone":"UTC"},"extra":[]}
php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30a841676.51726260] Processed:  App\Jobs\ProcessExperimentalJob
php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30a913a25.80490108] Processing: App\Jobs\ProcessExperimentalJob
php-library-worker-queue-example | {"message":"Place the message here for the processing queue received at: 2021-01-30 22:51:54:579488 Processed at: 2021-01-31 00:47:38:251189","context":[],"level":200,"level_name":"INFO","channel":"local","datetime":{"date":"2021-01-31 00:47:38.251229","timezone_type":3,"timezone":"UTC"},"extra":[]}
php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30a913a25.80490108] Processed:  App\Jobs\ProcessExperimentalJob
php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30abadad8.37346333] Processing: App\Jobs\ProcessExperimentalJob
php-library-worker-queue-example | {"message":"Place the message here for the processing queue received at: 2021-01-30 22:51:54:753117 Processed at: 2021-01-31 00:47:38:253215","context":[],"level":200,"level_name":"INFO","channel":"local","datetime":{"date":"2021-01-31 00:47:38.253247","timezone_type":3,"timezone":"UTC"},"extra":[]}
php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30abadad8.37346333] Processed:  App\Jobs\ProcessExperimentalJob
php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30b0eb9b5.50128892] Processing: App\Jobs\ProcessExperimentalJob
php-library-worker-queue-example | {"message":"Place the message here for the processing queue received at: 2021-01-30 22:51:55:052662 Processed at: 2021-01-31 00:47:38:254837","context":[],"level":200,"level_name":"INFO","channel":"local","datetime":{"date":"2021-01-31 00:47:38.254869","timezone_type":3,"timezone":"UTC"},"extra":[]}
php-library-worker-queue-example | [2021-01-31 00:47:38][6015e30b0eb9b5.50128892] Processed:  App\Jobs\ProcessExperimentalJob

As we can see above. We saw that when our worker service verified that there were messages to process he executed them,

we saw his output, as he is using /dev/stderr to write logs:
We can see it with the following command:

docker-compose logs worker-queue

Checking messages after processing in the application

We have seen the operation of a mini-application and the communication between its components.

We close here.
I hope I was clear in my explanation.
Thanks for your attention, see you next time!