Dockerize realtime chat application with Laravel, Nginx, VueJS, Laravel Echo, Redis, SocketIO

Tram Ho

Hi everyone, welcome back to my Docker and CICD series.

Wishing everyone a warm and peaceful Christmas ??

A few days ago, when the spirit of blogging was going up, my eyes went on strike again after a period of too much computer time, today the “window of the soul” seems to be good again, I slowly wrote a blog again. for everyone ?

Whatever you do, remember to stay healthy everyone, when Tet comes, you have to have health to work to get money to give to your teacher ??

In the previous article I showed you the Dockerize NodeJS application with mysql, redis, … along with the setup for dev and production environments.

In this article we will play “hardcore” by Dockerize Chat application realtime with Laravel, VueJS, Laravel Echo, SocketIO, Redis along with the setup of Laravel Horizon and Laravel Schedule Task.

Sorry for the name of this article I left a bit long, the purpose to read through the title you will be clearer and for those who search from google, it will be easier to find offline.

Money Setup

As usual, you need to install Docker and Docker-compose, if you have not already done so, see in my first post.


You can clone source code here (branch master )

In this article we will only care about the docker-laravel-realtime-chat-app folder.

Application overview

This application was made and deployed to run production here, you can go and try it out


  • The application has chat rooms for users to join
  • Each chat room will have 1 shared chat box, all users in the room can message here
  • Along with that is the list of users in the chat room, click on any one user to private message with that person
  • Every 1 minute will automatically appear the welcome message of Bot (using Laravel Schedule Task )
  • Detect user typing, or viewing messages, …
  • You can choose the expressive messages like Facebook Messager: Love, Haha, Wow, ….. ?

Shake the brain before use

Before we go into the Dockerfile configuration, we will first “shake the brain” to analyze what services this project has, what Dockerfile you need. ?

  • Similarly all Dockerize Laravel applications , to run the project’s minimum basic service we will use 2 app (php-fpm there) and service webserver (using nginx)
  • Having a database to store messages, a list of users, a chat room, … -> requires a db service
  • Having queue job -> need a redis service
  • Having realtime with Laravel Echo, socketio -> requires a laravel-echo-server service
  • At the same time we also need to add a service adminer to administer the MySQL database for visualization (this is similar to the phpmyadmin type) ? )

So we all have 6 services corresponding to 6 containers that need to be initialized to run the application.

In this article, we will write Dockerfile for 2 services, app and laravel-echo-server , the rest of the services we use are always provided.

Build Docker image

In this article because we have quite a lot of services, so the entire setup + data section of Mysql, redis we are stored in a folder called .docker.

At the root project (folder docker-laravel-realtime-chat-app , in this article I said always the project root because the folder name is too long ?? ), create a folder named .docker .

Configure Dockerfile for Laravel Echo Server

First we will proceed to configure Dockerfile and build image for laravel-echo-server service .

In the .docker folder, create a folder called laravel-echo-server

This service is rightly named above as Laravel Echo Server to handle the broadcast from Laravel to the browser

Basically this service is quite simple, written in nodejs, this service will almost no change after building, we will be less active on this service.

To run the service written in NodeJS in the Docker environment, we will use PM2.

In the laravel-echo-server folder, create a file called laravel-echo-server.json with the following content: (This file is a configuration for Laravel Echo Server)

Next, because we use PM2 to run this service, we will create a configuration file for PM2, still in the laravel-echo-server folder, create echo.json file with the following content:

Finally, we create the Dockerfile file to configure the image we need to build (still in the laravel-echo-server directory, guys ):

After configuring the configuration directory for our laravel echo server , it will look like this:


It’s okay, but in this article we will not build the image immediately with the command docker build … as usual, but we will build with docker-compose later (we’ll see in a little later. ? )

Configuration for service app

Next is that we will configure the service app, the section below will have a lot of things related to Linux, I will explain into the remaining important things what you wonder then search google continue to understand more.

Continue to shake the brain before use

As at the beginning of the article I have introduced in this article we will have Laravel Horizon and Laravel Schedule Task. So in the service app we will run the process (process as follows):

  • PHP-FPM to run PHP code (this process is required)
  • Crontab for Laravel Schedule Task (this process is optional)
  • Laravel Horizon (this process is also optional)

Above I have 2 optional processes, ie we can use it or not, the application can still run without those 2 processes, later we will specify the configuration later.

And in Linux to run and manage many processes, I will use a fairly common tool called supervisor offline.

We will create configuration files corresponding to the above processes, then the supervisor will read and start those processes.

Supervisor configuration

In the .docker folder you create yourself a file named supervisord.conf , with the following content:

Next, in the .docker folder, create a folder called supervisor.d , this folder will contain the image files for the processes mentioned above.

In the supervisor.d folder, create the php-fpm.conf file with the following content:

Still in the supervisor.d folder, create a file called horizon.conf.default with the following content:

The configuration is similar to the php-fpm process, except that this process will be run under the user named www-data , this user will be made available from php-fpm . The reason is because we do not need the root privileges to run this command, because later the entire code when building the image will be set to the www-data user (to limit the rights of the user running the project, only for the user). rights sufficient to run)

Next, it is still in the supervisor.d folder, we create 2 files cron.conf.default , and worker.conf.default with the following contents (I quickly explain it no further)

File cron.conf.default


After configuration is complete, our .docker folder will look like this:


You may wonder:

  • Why is the name of the php-fpm process only without the default suffix? As I said above, the php-fpm process is required for our PHP code to run so we always need the process, while the remaining processes are optional (optional), without them the application of I still run
  • Where is the worker.conf.default file coming from? do you need to use it or not Because Laravel Horizon has automatically created workers for us, if you run Horizon, you won’t need worker.conf.default anymore, but if you don’t run Horizon, we need this file for Queue Job to have Can run

Ok that configuration is okay. We move to Dockerfile ?

Configure Dockerfile

At the project root (folder docker-laravel-realtime-chat-app ) you create the Dockerfile file with the following content:

Explain some places that may have questions:

  • We started from a built-in image of PHP-FPM I got here
  • Below we have created two environment variables ENABLE_CRONTAB and ENABLE_HORIZON to specify that we will use the process crontab and horizon later (as in the previous section, I said that these optional processes can be used or not, here we use both )
  • Next we have ENTRYPOINT , here are the uploads so we can optionally use processes like: crontab, horizon or worker we talked about. When building the image, the file will be run, including some setups (this file will be created at the bottom)
  • Finally, we start the supervisor with CMD

The remaining places in the Dockerfile file you can see in the previous articles I have explained offline

Entrypoint configuration

As I said above, we will use a file called to set the option to use processes like crontab, horizon or worker, depending on the environment variable we set.

In the .docker folder you create yourself a file named with the following content:

Looking at the file above is already clear, right? Depending on the environment variable we set, we can choose to use a certain process or not.

If used, rename the file of the process to remove the default suffix, and if not use, we delete the configuration file

Configure .dockerignore

Before building the image we will configure .dockerignore to tell Docker “to skip some files, don’t copy them inside the image when building”. ?

At the root project (folder docker-laravel-realtime-chat-app ) you create .dockerignore file with the following content:

This is quite similar to the content of gitignore, isn’t it ?

Note: although using folders like node_modules we don’t have, we still ignore them because later when building VueJS will need node_modules and in the future we can build this project many more times, so let’s add it first. ?

Ok, everything is fine for the service app , but here we will not build the image right away but we will build with docker-compose later.

Nginx configuration

Similarly in post Dockerize Laravel application we will need to set up Nginx webserver.

In the .docker folder, create nginx.conf file with the following content:

Notice above when with the PHP code, we will redirect the request into the service app so that the service app has PHP-FPM working, and with , we redirect the job to the laravel-echo-server service.

Create a folder to mount the volume

Similar to the Dockerize NodeJS article with Mongo and Redis in this article, we will create folders to save data from MySQL and Redis so that when our project restarts, all data will remain intact.

In the .docker folder you create yourself 1 folder named data , inside the data folder you create yourself 2 folders named db (save data for MySQL) and redis okay ?

At this point, our .docker folder will look like this:


Run the application

Configure docker-compose

To run this application, we will create a docker-compose file with the following content:

The content of the file above is similar to the previous article, right? There are some places I explain so if any of you have any questions:

  • In the service db, the environment information will be taken from variables in the .env file (we will create it shortly).
  • Similarly in the laravel-echo-server service , we will not use the environment to set an environment variable that Laravel Echo Server will read directly from the .env file (this section is specified in the github of the Laravel echo server )
  • In the service webserver and adminer in the mapping port, we have to leave the values ​​of two environment variables later to be defined in the .env file.
  • As I said in the service app and laravel-echo-server will be built using docker-compose , you can see we have a build field and specify the context (the context is in which path) plus what is Dockerfile’s name . When running the app, docker-compose will find and build each service for us

Create .env file

Next we will create a .env file. You create a file named .env and copy the content from the file .env.example to offline.

Then you open the file .env and fix some places as follows:


  • Above we have the configuration parameters connected to the database, you notice DB_HOST must match the name of the service we defined in docker-compose.yml . Same for the Redis configuration section

Moment of truth

Yes, so after a 1-year long configuration post, it’s time for us to test this project to see if it’s hard to get any results. ??

You run the following command to launch the project:

After the above command is successful, open the browser at localhost: 4000 .

And ….. MUD ? blank, see nothing ??

The problem here is that we have not run composer install or npm install so the service app (the Laravel ** part ** fails)

So the problem is: how can you run composer or npm while the service app environment doesn’t have Composer or NodeJS?

Install dependencies (composer install, npm install, …)

As in Dockerize VueJS, I mentioned using temporary containers to install dependencies instead of installing directly into images.

This will help to reduce the size of the image, because the installation of this dependencies does not occur often, but we usually only do it once in the beginning of the setup project.

You run the following command in turn:


  • First we create a temporary container from the image compose (with pre-installed composer) and we run composer install with some options behind (search google for more about these options)
  • Next we create a temporary container still from the image composer and run dump-autoload to load the PHP library classes
  • Next we create a container from the image node and run npm install we have the –production option “to install only things in the dependencies section of the package.json file
  • Finally, we build the VueJS code (if you want to watch it, change it to run watch).

Moment of truth (part 2)

Once completed we return to the browser and F5:

Docker laravel

I have seen the app launch and report that there is no key yet.

Before running the command to create the key, please note: all php artisan commands from now on we will always run as docker-compose exec app php artisan …. (note the first part). Why? Because when running outside, Laravel will rely on the context of the external environment to run, so commands like migrate will fail. So to sync and for you to know, we always run with docker-compose exec … okay

We run the following command to create the key and create a DB and seed as well

Then we reloaded the browser and …… BUOM ?

Docker Laravel

Docker laravel

Was successful ?

You try to create 2 accounts and chat with each other to see how. This part I let you take a selfie ??

To dabble in the database administration section, access localhost: 8080 ?

To access the Horizon section you access the address localhost: 4000 / horizon okay

Since we have mounted the volume from the root environment into the container, you can directly modify the code and see the changes. Note if you fix the VueJS code, remember to run npm ?


Phewuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu …….. The song is filled with the sky, billions of new knowledge, blurred vision, and whirling mind.

Dockerize is a chat application that spray nasal blood ??

This song is also quite long, but I do not want to split into 2 tracks because it will be a bit in the middle. The Laravel code I have made available for you and we only focus on the Docker.

In this article there is a lot of knowledge related to Linux, I can not explain it little by little for you, but you can copy and paste and search google will have all the information offline.

There will also be parts of the Linux knowledge that you see as “even if the search does not understand”, then we “accept” to use and gradually absorb it. In the past, when I first dockedize Laravel, some parts about my supervisor were almost blind, who told me what to do, now I’m getting better. ?? . Personally, I see through these projects our Linux submission will increase significantly ?

Through this article hope you have understood how to Dockerize a project Laravel full options ? , full of things like DB, Redis, Queue Job, Cronjob, … in what would be like offline. From there apply and apply into practice accordingly. At the same time we also note that even though we use many things MySQL, Redis, Nginx, Adminer, PHP, Composer NodeJS … but all are run in Docker containers, our original environment is still “virgin”. ??

If there is a problem, please leave a comment for me.

The entire source code to the final step of this article I put here (branch complete-tutorial okay)

Thank you for watching. See you in the following post ^^

Share the news now

Source : Viblo