⬆️ ⬇️

Dockarize Socket.io, redis and php

To transfer data to the server on the php client, you can use the following algorithm:



  1. The php server publishes data to the redis channel.
  2. The node server subscribes to events in the corresponding redis channel and when

    the onset of the data arrival event publishes this data already in

    socket.io
  3. The client subscribes to the socket.io messages and processes them upon receipt


The source code of the project can be found on github



Here I will move in very small steps.

The project will use a bunch of nginx and php-fpm and I will start with the settings

nginx.



Nginx configuration



Let's start creating docker-compose.yml in the root folder of our project.



 # docker-compose.yml version: '3' services: nginx: image: nginx ports: - 4400:80 


Open in the browser: http://localhost:4400 and see the standard greeting

nginx.

Now we configure nginx to give the static contents of the folder

./www/public .

First create folders



 mkdir -pv www/public 


Create a file ./www/pulbic/index.html



 <!-- www/public/index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>Hello World!</h1> </body> </html> 


Create a nginx configuration file - nginx/conf/custom.conf . To start

copy the standard /etc/nginx/conf.d/default.conf .

Change docker-compose.yml



  services: nginx: image: nginx + volumes: + - ./nginx/conf/custom.conf:/etc/nginx/conf.d/default.conf ports: - 4400:80 


Recreate nginx container



 docker-compose up -d 


And once again we see in the browser at http://localhost:4400 standard

greeting nginx.

Make changes

docker-compose.yml



  image: nginx volumes: - ./nginx/conf/custom.conf:/etc/nginx/conf.d/default.conf + - ./www:/www ports: - 4400:80 


nginx/conf/custom.conf



  #access_log /var/log/nginx/host.access.log main; location / { - root /usr/share/nginx/html; + root /www/public; index index.html index.htm; } 


Now, at http://localhost:4400 , 'Hello World!' Is displayed. from file

www/public/index.html .

Breakthrough is difficult to call, but we are definitely moving in the right direction.



Php setup



Let's start by creating folders for storing container settings files.



 mkdir -pv php/conf 


Next, create a php/Dockerfile



 FROM php:7-fpm RUN apt-get -qq update && apt-get -qq install \ curl \ > /dev/null ENV PHPREDIS_VERSION 3.0.0 RUN mkdir -p /usr/src/php/ext/redis \ && curl -L https://github.com/phpredis/phpredis/archive/$PHPREDIS_VERSION.tar.gz | tar xvz -C /usr/src/php/ext/redis --strip 1 \ && echo 'redis' >> /usr/src/php-available-exts \ && docker-php-ext-install redis 


And make changes to docker-compose.yml



  - ./www:/www ports: - 4400:80 + php: + build: ./php + volumes: + - ./www:/www + environment: + - REDIS_PASSWORD=${REDIS_PASSWORD} 


We also need to make changes to the nginx settings so that the files with the extension

.php processed by php-fpm .

Modify the nginx/conf/custom.conf file as follows



  # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # -#location ~ \.php$ { -# root html; -# fastcgi_pass 127.0.0.1:9000; -# fastcgi_index index.php; -# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; -# include fastcgi_params; -#} +location ~ \.php$ { + root /www; + fastcgi_pass php:9000; + fastcgi_index index.php; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + fastcgi_param SCRIPT_FILENAME /www/public/$fastcgi_script_name; + include fastcgi_params; +} 


It remains to create the file www/public/info.php with the following code



 <?php phpinfo(); 


Restart our container



 docker-compose restart 


And now at http://localhost:4400/info.php information about

php settings

Experiment a little more and create the file www/Test.php



 <?php class Test { public function prn() { echo 'Success'; } } 


And the contents of the file www/public/info.php replace with the following:



 <?php require_once( implode( DIRECTORY_SEPARATOR, [ dirname(__DIR__), 'Test.php' ] ) ); $test = new Test(); $test->prn(); 


Now at the address http://localhost:4400/info.php 'success' is displayed, and this

means that php-fpm scripts are located in the www folder, and through

browser they are not available. Those. we keep moving in the right direction.



Redis setup



This is perhaps the shortest part.

Redis in this project will not be accessible from the external network, but password protection

set up.

To do this, create a file .env



 REDIS_PASSWORD=eustatos 


Make changes to docker-compose.yml



  build: ./php volumes: - ./www:/www + redis: + image: redis + command: ["sh", "-c", "exec redis-server --requirepass \"${REDIS_PASSWORD}\""] 


To test the connection to redis, edit the file www/public/info.php



 <?php $redis = new Redis(); //    redis $redis->connect( 'redis', 6379 ); // . 'eustatos' - ,      `.env` $redis->auth($_ENV['REDIS_PASSWORD']); //     'eustatos' $redis->publish( 'eustatos', json_encode([ 'test' => 'success' ]) ); //   $redis->close(); 


Restart the container



 docker-compose restart 


Now connect to the redis server



 docker-compose exec redis bash 


Let's go to the command line. 'eustatos' is the password we previously set in

the .env file



 # redis-cli -a eustatos 


Subscribe to the 'eustatos' channel (the name is arbitrary, so that everything works,

match the channel name that we defined in the file

www/public/info.php )



 > subscribe eustatos 


After all these preparations, go to the browser at

http://localhost:4400/info.php and watch, as in the terminal, where we

connected to redis appear about the following lines:



 1) "message" 2) "eustatos" 3) "{\"test\":\"success\"}" 


So we have become even closer to our goal.



Configure socket.io



Create a folder where our socket.io server files will be located



 mkdir socket 


Make changes to docker-compose.yml



  redis: image: redis command: ["sh", "-c", "exec redis-server --requirepass \"${REDIS_PASSWORD}\""] + socket: + image: node + user: "node" + volumes: + - ./socket:/home/node/app + ports: + - 5000:5000 + working_dir: /home/node/app + command: "npm start" 


Go to the socket folder



 cd socket 


Install the necessary packages



 npm init -y npm i -S socket.io redis express 


After that, add lines to the file socket/package.json



 { "name": "socket-php-example", "version": "1.0.0", "main": "index.js", "author": "eustatos <astashkinav@gmail.com>", "license": "MIT", + "scripts": { + "start": "node index.js" + }, "dependencies": { "express": "^4.16.3", "redis": "^2.8.0", "socket.io": "^2.1.0" } } 


Create the file socket/index.js



 const express = require('express'); const app = express(); const http = require('http').Server(app); const port = process.env.PORT || 5000; app.get( '/', function(req, res, next) { res.send('success'); } ); http.listen( port, function() { console.log('Listen at ' + port); } ); 


Restart our container



 docker-compose restart 


After that, the browser at http://localhost:5000 displays "success".

So we are a little closer to our goal. There are very few.

Change the file socket/index.js



 const express = require('express'); const app = express(); const http = require('http').Server(app); const io = require('socket.io')(http); //   redis const subscriber = require('redis').createClient({ host: 'redis', port: 6379, password: 'eustatos' }); //      redis subscriber.on('message', function(channel, message) { //     redis   socket.io io.emit('eustatosRoom', message); }); //   socket.io io.on('connection', function(socket){ //    redis 'eustatos'  callback subscriber.subscribe('eustatos'); }); const port = process.env.PORT || 5000; http.listen( port, function() { console.log('Listen at ' + port); } ); 


This completes the socket.io container configuration.



Configuring the client application



The client application can be deployed in any of our containers, but

for the purity of the experiment, deploy it in a separate container.

We will place the client application files in the client folder.



 mkdir client 


Create a file client/index.html



 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script> <script> const socket = io( window.location.protocol + '//' + window.location.hostname + ':5000' ); socket.on( 'eustatosRoom', function(message) { console.log(JSON.parse(message)); } ); </script> </body> </html> 


Change docker-compose.yml



  ports: - 5000:5000 command: "npm start" + client: + image: nginx + volumes: + - ./client:/usr/share/nginx/html + ports: + - 8000:80 


Restart our container



 docker-compose restart 


First open in the browser http://localhost:8000 . To demonstrate the result

Our works need to open the developer panel.

Nothing is displayed yet.

Open the address http://localhost:4400/info.php in another tab or window and look at the console panel of our client’s developer. We should see:



 {test: "success"} 


This means that our server has successfully transferred data to the client application.



')

Source: https://habr.com/ru/post/353212/



All Articles