質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
docker-compose

docker-composeとは、複数のコンテナで構成されるサービスを提供する手順を自動的し管理を簡単にするツール。composeファイルを使用しコマンド1回で設定した全サービスを作成・起動することが可能です。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

1回答

3336閲覧

docker-composeで構築したlaravel-echo-serverにリクエストが通らない。

GrayWingAliance

総合スコア218

docker-compose

docker-composeとは、複数のコンテナで構成されるサービスを提供する手順を自動的し管理を簡単にするツール。composeファイルを使用しコマンド1回で設定した全サービスを作成・起動することが可能です。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2020/01/12 06:15

編集2020/01/12 17:26

問題点

ブラウザから、laravel-echo-serverに接続しようとするとERR_CONNECTION_RESETのエラーが発生し、WebSocket通信が開始されない。

構築したdockerの構成

使用サーバ一覧

以下のコンテナ名を使用しています。

  • nginx
  • php-fpm
  • echo-server←今回接続できていないサーバ
  • mysql
  • redis
  • npm(JavaScriptビルド用)
  • npmi(npm install用)
  • composer(composer install用)

使用したdocker-compose.yaml及びdockerfile

docker

1version: '3' 2services: 3 nginx: 4 image: nginx:latest 5 volumes: 6 - ./src/laravel:/usr/share/nginx/html 7 - ./container/nginx/default.conf:/etc/nginx/conf.d/default.conf 8 ports: 9 - 80:80 10 links: 11 - php-fpm 12 composer: 13 image: composer:latest 14 command: composer install 15 working_dir: /data 16 volumes: 17 - ./src/laravel:/data 18 php-fpm: 19 build: ./container/php-fpm 20 volumes: 21 - ./src/laravel:/var/www/html 22 - ./container/php-fpm/www.conf:/usr/local/etc/php-fpm.d/www.conf 23 depends_on: 24 - composer 25 links: 26 - mysql 27 - redis 28 npm: 29 build: ./container/npm 30 command: npm run watch-poll 31 working_dir: /data 32 volumes: 33 - ./src/laravel:/data 34 depends_on: 35 - npmi 36 npmi: 37 build: ./container/npm 38 command: npm i 39 working_dir: /data 40 volumes: 41 - ./src/laravel:/data 42 echo-server: 43 build: ./container/npm 44 command: laravel-echo-server start 45 working_dir: /data 46 volumes: 47 - ./src/laravel:/data 48 expose: 49 - 6001 50 links: 51 - redis 52 ports: 53 - 6001:6001 54 mysql: 55 image: mysql:8.0 56 command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci 57 environment: 58 MYSQL_DATABASE: phpunit_tester 59 MYSQL_ROOT_PASSWORD: password 60 MYSQL_USER: phpunit_tester 61 MYSQL_PASSWORD: password 62 TZ: Asia/Tokyo 63 ports: 64 - 3306:3306 65 volumes: 66 - ./container/mysql/data:/var/lib/mysql 67 - ./container/mysql/initdb.d:/docker-entrypoint-initdb.d 68 redis: 69 image: redis:latest 70 ports: 71 - 6379:6379

container/npm/Dockerfle

1FROM alpine:latest 2 3# ホストのUIDと同条件のユーザを作成 4ARG DOCKER_UID=1000 5ARG DOCKER_USER=docker 6ARG DOCKER_PASSWORD=docker 7RUN adduser -s /bin/ash -u ${DOCKER_UID} ${DOCKER_USER} -D && \ 8# npmのインストール 9apk add --update nodejs npm && \ 10npm i -g laravel-echo-server 11# デフォルトユーザの変更 12USER ${DOCKER_USER}

php-fpmでも、Dockerfileを使用していますが、今回はあまり関係なさそうなため、省略します。

使用したlaravel-echo-server.json

laravel

1{ 2 "authHost": "http://localhost", 3 "authEndpoint": "/broadcasting/auth", 4 "clients": [ 5 { 6 "appId": "83a5c632a785327f", 7 "key": "576186c4d59b7dd113c75a786328b9d7" 8 } 9 ], 10 "database": "redis", 11 "databaseConfig": { 12 "redis": { 13 "port": "6379", 14 "host": "redis", 15 "keyPrefix": "phpunit-tester-echo-server" 16 }, 17 "sqlite": { 18 "databasePath": "/database/laravel-echo-server.sqlite" 19 } 20 }, 21 "devMode": true, 22 "host": "localhost", 23 "port": "6001", 24 "protocol": "http", 25 "socketio": { 26 "wsEngine": "ws" 27 }, 28 "secureOptions": 67108864, 29 "sslCertPath": "", 30 "sslKeyPath": "", 31 "sslCertChainPath": "", 32 "sslPassphrase": "", 33 "subscribers": { 34 "http": true, 35 "redis": true 36 }, 37 "apiOriginAllow": { 38 "allowCors": true, 39 "allowOrigin": "http://localhost:80", 40 "allowMethods": "GET, POST", 41 "allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id" 42 } 43}

フロントエンド側の実装

まず、laravel側のルーティングを以下のようにしました

web.php

1 2Route::get('/listener', function(){ 3 $hello = "Hello World!"; 4 return view('listener'); 5});

viewファイルはnpmでビルドしたapp.jsを使用しています。

listener.blade.php

1<html lang='ja'> 2<head> 3 <meta charset="utf-8"> 4 <meta name="csrf-token" content="{{csrf_token()}}"> 5</head> 6<body> 7listener 8<div id='app'></div> 9<script src="{{ asset('js/app.js') }}"></script> 10</body> 11</html>

bootstrap.jsをecho-serverに対応させることで、リクエストは投げられることが確認できましたが、ERR_CONNECTION_RESETのエラーが出てきてしまい、接続できませんでした。

bootstrap.js

1window._ = require('lodash'); 2 3/** 4 * We'll load the axios HTTP library which allows us to easily issue requests 5 * to our Laravel back-end. This library automatically handles sending the 6 * CSRF token as a header based on the value of the "XSRF" token cookie. 7 */ 8 9window.axios = require('axios'); 10 11window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 12 13/** 14 * Echo exposes an expressive API for subscribing to channels and listening 15 * for events that are broadcast by Laravel. Echo and event broadcasting 16 * allows your team to easily build robust real-time web applications. 17 */ 18 19import Echo from 'laravel-echo'; 20 21window.io = require('socket.io-client') 22 23window.Echo = new Echo({ 24 broadcaster: 'socket.io', 25 host: 'http://localhost:6001' 26 27}); 28 29window.Echo.channel('public-event') 30.listen('PublicEvent', (e) =>{ 31 console.log(e) 32}); 33

これをapp.jsでrequireしたものをbuildしているだけです。

発生したエラー

(追記: この挙動Chromiumでのものです。)
http://localhost/listenerに接続するとDeveloper tool のNetworkタブに以下のエラーが出ました。
RequestURL: http://localhost:6001/socket.io/?EIO=3&transport=polling&t=M-OK9jG
RequestMethod: GET
エラー:
net::ERR_CONNECTION_RESET
(たまに、net::ERR_SOCKET_NOT_CONNECTEDが出ることもあるようです。)

確認したこと

ポートの開放確認
ホスト機から以下のコマンドを送信しました。

$ nc -vz localhost 6001

結果は以下のとおりです。

Connection to localhost 6001 port [tcp/x11-1] succeeded!

Firefoxでの接続確認
Firefoxでの接続の場合、エラーが以下のようになりました。

クロスオリジン要求をブロックしました: 同一生成元ポリシーにより、http://localhost:6001/socket.io/?EIO=3&transport=polling&t=M-OZGN7 にあるリモートリソースの読み込みは拒否されます (理由: CORS 要求が成功しなかった)。

知りたいこと

Laravel-Echo-Serverにきちんと接続できる方法。

retlatさんの解答を受けて、、、

内部トラフィック増えそうといったけれど、本番環境でロードバランサ噛ませるなら、別にそれでもいいかな、と思いつつ…ただ、なんか気持ち悪いので、別ポートで接続できるようにしたい。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/01/12 06:36

リンクさせてないからじゃね
GrayWingAliance

2020/01/12 06:46

現状、リンクの状況は nginx -> php-fpm php-fpm -> mysql php-fpm -> redis echo-server -> redis となっていますが、他にリンクの必要がある部分はどこになるでしょうか?
guest

回答1

0

エラーメッセージに出ているようにCORS要求がブロックされています
NginxとEcho Serverのポートが異なっているため、http://localhostは一致していても別のオリジンと認識されています

Nginxでリクエストを受けてEcho Serverへリバースプロキシするように設定する、もしくはLaravelでAccess-Control-Allow-Originヘッダーを出力することで接続できるようになると思います

投稿2020/01/12 13:36

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GrayWingAliance

2020/01/12 17:15

laravel-echo-server.jsonでCORSの許可を行っているので、ヘッダーに自動的に追加されるものと思っていたのですが違うのでしょうか? 一応ビュー側にAccess-Control-Allow-Originヘッダーを追加してみたのですが駄目でした。 Nginxをリバースプロキシとして両方80番ポートで接続したらうまく行きましたが、内部トラフィックに無駄が増えそうなのでできるなら、Laravel-Echo-Serverから直に読み出したいと思っております。 もし、どうしても出来ないようであれば、この方法を取ってみたいと思います。
退会済みユーザー

退会済みユーザー

2020/01/13 01:46

80番ポートからHTMLを配信し6001番にWebSocketを繋ぐのであれば、80番のレスポンスに6001番を許可するヘッダーを出力する必要があります jsonファイルには6001番の記述はありませんので、そこが原因かと思います
GrayWingAliance

2020/01/13 06:03

CORSは共有される側のリソースが共有先のIPやポートが一致するかを確認するためのものであるため、その認識は間違っていると思います。 今回であれば、ポート6001番のリソース側で、80番のページからアクセスするのを許可するのが正解です。 また、もしretlatさんの言うとおり6001番の許可が必要であるとすれば、前述のビュー側にAccess-Control-Allow-Originヘッダを追加したときにうまく行っていると思われます。
退会済みユーザー

退会済みユーザー

2020/01/13 13:30

確かに間違っていました 失礼しました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問