ứng dụng realtime với Laravel, Nginx, Laravel Echo, Redis, SocketIO
Dockerize ứng dụng realtime với Laravel, Nginx, Laravel Echo, Redis, SocketIO
hế lô mọi người! sau thời gian dài bỏ bê hôm nay mình mới có cảm hứng ngồi viết bài, mong mọi người dành chút thời gian cho bài viết của mình nha! :))
bài viết ngày hôm nay mình sẽ viết về realtime với laravel, nginx, laravel-echo, reidis sử dụng docker, vì bài viết khá dài nên mọi người chuẩn bị ly cafe nhâm nhi cho đỡ buồn ngủ nha.
Nói đến ứng dụng realtime thì chắc quá quen thuộc với mọi người rồi nên mình xin phép ko nói về nó để làm gì, ứng dụng vào cái gì nữa mà mình sẽ bắt đầu ngay vào nội dung luôn.
Tiền setup
Để setup ứng dụng các bạn cần cài đặt Docker và Docker-compose nha.
đầu tiên mình sẽ tạo 1 file docker-compose.yml
file của mình sẽ như thế này:
version: '3.7'
services:
# PHP-FPM - Service
app:
build:
context: .
dockerfile: ./Docker/Dockerfile
restart: unless-stopped
tty: true
working_dir: /var/www
volumes:
- ./:/var/www
- ./Docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network
# NGINX - Service
nginx:
image: nginx:alpine
restart: unless-stopped
tty: true
ports:
- "${NGINX_HOST_HTTP_PORT}:80"
volumes:
- ./:/var/www # vùng chứa
- ./Docker/nginx/conf.d/:/etc/nginx/conf.d/
depends_on:
- redis
networks:
- app-network
# MariaDB - Service
db:
image: mariadb:10.5.6
restart: unless-stopped
tty: true
ports:
- "33061:3306"
environment:
MYSQL_DATABASE: db_1
MYSQL_PASSWORD: 123456
MYSQL_ROOT_PASSWORD: 123456
MYSQL_USER: root
SERVICE_NAME: mysql
volumes:
- mariadbdata:/var/lib/mysql #cho phép dừng và khởi động lại dbdịch vụ mà không làm mất dữ liệu.
- ./Docker/mysql/my.cnf:/etc/mysql/my.cnf
networks:
- app-network
### Redis ################################################
redis:
build: ./Docker/redis
volumes:
- ${DATA_PATH_HOST}/redis:/data
ports:
- "${REDIS_PORT}:6379"
networks:
- app-network
### Laravel Echo Server #######################################
laravel-echo-server:
build:
context: ./Docker/laravel-echo-server
args:
- CHANGE_SOURCE=${CHANGE_SOURCE}
volumes:
- ./Docker/laravel-echo-server/laravel-echo-server.json:/app/laravel-echo-server.json:ro
ports:
- "${LARAVEL_ECHO_SERVER_PORT}:6001"
links:
- redis
networks:
- app-network
# Volumes
volumes:
mariadbdata:
driver: ${VOLUMES_DRIVER}
nginx:
driver: ${VOLUMES_DRIVER}
redis:
driver: ${VOLUMES_DRIVER}
# Networks
networks:
app-network:
driver: bridge
Như các bạn thấy ở đây mình đang dùng các services là app, nginx, db, redis, laravel-echo-server
Tiếp theo trong project của mình mình sẽ tạo 1 foder là Docker, đây là cấu trúc foder của mình

mình sẽ bỏ qua services app, nginx, db vì bài viết khá dài và nó cũng khá quen thuộc với mọi người rồi.
theo như mình hiểu thì laravel-echo-server nó sẽ echo ra data mỗi khi event push data vào redis, bạn nào hiểu rõ thì chỉ giúp nha :))
Trong foder laravel-echo-server mình sẽ tạo những file sau:
1: file laravel-echo-server.json
{
"authHost": "localhost",
"authEndpoint": "/broadcasting/auth",
"clients": [],
"database": "redis",
"databaseConfig": {
"redis": {
"port": "6379",
"host": "redis"
}
},
"devMode": true,
"host": null,
"port": "6001",
"protocol": "http",
"socketio": {},
"sslCertPath": "",
"sslKeyPath": ""
}
2: file package.json
{
"name": "laravel-echo-server-docker",
"description": "Docker container for running laravel-echo-server",
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"laravel-echo-server": "^1.5.0"
},
"scripts": {
"start": "laravel-echo-server start"
}
}
Trong foder redis mình tạo 1 file Dockerfile như sau:
FROM redis:latest
LABEL maintainer="Mahmoud Zalt <mahmoud@zalt.me>"
## For security settings uncomment, make the dir, copy conf, and also start with the conf, to use it
#RUN mkdir -p /usr/local/etc/redis
#COPY redis.conf /usr/local/etc/redis/redis.conf
VOLUME /data
EXPOSE 6379
#CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]
CMD ["redis-server"]
File .env mình sẽ cấu hình như sau
BROADCAST_DRIVER=redis
REDIS_HOST=redis
Bây giờ mình sẽ run docker-compose up --build

như các bạn thấy laravel-echo-server đã được start
Tiếp theo mình sẽ tạo 1 event như sau:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class CreateOrder implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public $order;
public function __construct($order)
{
$this->order = $order;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('orders');
}
public function broadcastAs()
{
return 'order.created';
}
public function broadcastWith()
{
return [$this->order];
}
}
bước tiếp theo các bạn run
npm install --save socket.io-client laravel-echo
trong file bootstrap.js các bạn thêm đoạn code như sau:
window._ = require('lodash');
import Echo from "laravel-echo"
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001',
transport: ['websocket']
});
ở file app.js
require('./bootstrap');
Echo.channel('orders')
.listen('.order.created', (e) => {
console.log(e);
});
console.log("Echo", Echo);
bây giờ npm run dev và f5 thử xem nha

OKE như vậy là đã connect được với socket rồi.
nào cùng test thử nào !!!
Route::get('/test', function () {
$order = [
'name' => "test",
'amount' => 12345,
];
event(new \App\Events\CreateOrder($order));
return view('welcome');
});
Gờ gọi đến link /test xem kết quả thế nào nhé



như vậỵ là được rồi đó :))
Bài này khá dài nên mình ko đi vào chi tiết cụ thể được, và các sắp xếp, trình bày chưa được logic cho lắm, mọi người review rồi cho mình xin ý kiến nha! rất mong được sự góp ý của mọi người