|
|||||||
Докеризируем Socket.io, redis и php
Время создания: 28.05.2018 11:11
Текстовые метки: php redis socket io docker websocket
Раздел: WebSocket
Запись: Velonski/mytetra-database/master/base/1527487860exwu6v5jgg/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Для передачи данных сервером на php клиенту можно использовать следующий алгоритм: Сервер php публикует данные в канал redis. Сервер node подписывается на события в соответствующем канале redis и при наступлении события поступления данных публикует эти данные уже в socket.io Клиент подписывается на сообщения socket.io и обрабатывает их при поступлении Исходный код проекта можно найти на github Здесь я буду двигаться очень маленькими шагами. В проекте будет использоваться связка nginx и php-fpm и начну я с настройки nginx. Настройка nginx Начнем создавать docker-compose.yml в корневой папке нашего проекта. # docker-compose.yml version: '3' services: nginx: image: nginx ports: - 4400:80 Откроем в браузере: http://localhost:4400 и увидим стандартное приветствие nginx. Теперь настроим, чтобы nginx отдавал статическое содержимое папки ./www/public. Сначала создадим папки mkdir -pv www/public Создадим файл ./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> Создадим файл конфигурации nginx — nginx/conf/custom.conf. Для начала скопируем стандартный /etc/nginx/conf.d/default.conf. Изменим docker-compose.yml services: nginx: image: nginx + volumes: + - ./nginx/conf/custom.conf:/etc/nginx/conf.d/default.conf ports: - 4400:80 Пересоздадим контейнер nginx docker-compose up -d И вновь наблюдаем по в браузере по адресу http://localhost:4400 стандартное приветствие nginx. Внесем изменения 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; } Теперь по адресу http://localhost:4400 отображается 'Hello World!' из файла www/public/index.html. Прорывом это назвать сложно, но мы определенно двигаемся в нужном направлении. Настройка php Начнем с создания папок для хранения файлов настроек контейнера. mkdir -pv php/conf Далее создадим 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 И внесем изменения в docker-compose.yml - ./www:/www ports: - 4400:80 + php: + build: ./php + volumes: + - ./www:/www + environment: + - REDIS_PASSWORD=${REDIS_PASSWORD} Также нам нужно внести изменения в настройки nginx, чтобы файлы с расширением .php обрабатывались php-fpm. Изменим файл nginx/conf/custom.conf следующим образом # 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; +} Осталось создать файл www/public/info.php со следующим кодом <?php phpinfo(); Перезапустим наш контейнер docker-compose restart И теперь по адресу http://localhost:4400/info.php отображается информация о настройках php. Еще немного поэкспериментируем и создадим файл www/Test.php <?php class Test { public function prn() { echo 'Success'; } } А содержимое файла www/public/info.php заменим на следующее: <?php require_once( implode( DIRECTORY_SEPARATOR, [ dirname(__DIR__), 'Test.php' ] ) ); $test = new Test(); $test->prn(); Теперь по адресу http://localhost:4400/info.php отображается 'success', а это означает, что php-fpm доступны скрипты расположенные в папке www, а через браузер они недоступны. Т.е. мы продолжаем двигаться в нужном направлении. Настройка redis Это, пожалуй, самая короткая часть. Redis в этом проекте не будет доступен из внешней сети, но защиту паролем настроим. Для этого создадим файл .env REDIS_PASSWORD=eustatos Внесем изменения в docker-compose.yml build: ./php volumes: - ./www:/www + redis: + image: redis + command: ["sh", "-c", "exec redis-server --requirepass \"${REDIS_PASSWORD}\""] Чтобы протестировать подключение к redis изменим файл 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(); Рестартуем контейнер docker-compose restart Теперь подключимся к серверу redis docker-compose exec redis bash Перейдем к командной строке. 'eustatos' — пароль, который мы ранее задали в файле .env # redis-cli -a eustatos Подпишемся на канал 'eustatos' (название произвольное, чтобы все работало, долно совпадать с названием канала, которое мы определили в файле www/public/info.php) > subscribe eustatos После всех этих приготовлений, переходим в браузере по адресу http://localhost:4400/info.php и наблюдаем, как в терминале, где мы подключались к redis появляются примерно следующие строки: 1) "message" 2) "eustatos" 3) "{\"test\":\"success\"}" Значит мы стали еще ближе к нашей цели. Настройка socket.io Созадим папку, где будут лежать файлы нашего socket.io сервера mkdir socket Внесем изменения в 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" Перейдем в папку socket cd socket Установим необходимые пакеты npm init -y npm i -S socket.io redis express После этого добавим в файл 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" } } Создадим файл 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); } ); Перезапустим наш контейнер docker-compose restart После этого в браузере по адресу http://localhost:5000 отображается "success". Значит мы еще чуть ближе к нашей цели. Осталось совсем немного. Изменим файл 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); } ); На этом настройка контейнера socket.io завершена. Настройка клиентского приложения Клиентское приложение можно развернуть в любом из наших контейнеров, но для чистоты эксперимента развернем его в отдельном контейнере. Файлы клиентского приложения разместим в папке client mkdir client Создадим файл 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> Изменим docker-compose.yml ports: - 5000:5000 command: "npm start" + client: + image: nginx + volumes: + - ./client:/usr/share/nginx/html + ports: + - 8000:80 Перезапустим наш контейнер docker-compose restart Откроем сначала в браузере http://localhost:8000. Для демонстрации результата наших трудов нужно открыть панель разработчика. Пока ничего не отображается. Откроем в другой вкладке или окне адрес http://localhost:4400/info.php и посмотри на консоль панели разработчика нашего клиента. Мы должны увидеть: {test: "success"} А это значит, что наш сервер благополучно передал клиентскому приложению данные. |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|