使用Docker和Nginx作为Laravel Websocket的反向代理时的问题
我已经使用Docker和Docker-Compose设置了Laravel项目。
我已经暴露了端口6001,它是运行 websocket 默认为默认值的端口NGINX基于文档,但是当我尝试使用域连接到WS服务器时,我会在Nginx日志文件上获取此错误:
上游读取上游响应标头的过早封闭连接从上游,客户: *,服务器:site.cpm,请求:“ get/app/7f0cb504a1426efd6854a03779a1c8a9?protocol=7&; ,上游: “ http://172.19.0.5:3030/app/7f0cb504a1426efd6854a03779a03779a1c8a9?protocol = 7& protcolcocol = 7& client = js&amp
;我什至无法使用直接IP和 港口。
我还应该提到,我的服务器上没有激活任何防火墙(至少据我所知)。
nginx配置文件:
map $http_upgrade $type {
default "web";
websocket "ws";
}
upstream websocket {
server php:6001;
}
server {
listen 80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /app/docker/nginx/certs/public-selfsigned.crt;
ssl_certificate_key /app/docker/nginx/certs/private-selfsigned.key;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
server_name panel.melodigram.app;
client_max_body_size 2048M;
index index.php index.html;
error_log /var/log/nginx/fpm.log;
access_log /var/log/nginx/access.log;
root /app/public_html;
location / {
try_files /nonexistent @$type;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location @web {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
location @ws {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
}
}
Websocet配置:websockets.php
<?php
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;
return [
/*
* Set a custom dashboard configuration
*/
'dashboard' => [
'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
],
/*
* This package comes with multi tenancy out of the box. Here you can
* configure the different apps that can use the webSockets server.
*
* Optionally you specify capacity so you can limit the maximum
* concurrent connections for a specific app.
*
* Optionally you can disable client events so clients cannot send
* messages to each other via the webSockets.
*/
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
/*
* This class is responsible for finding the apps. The default provider
* will use the apps defined in this config file.
*
* You can create a custom provider by implementing the
* `AppProvider` interface.
*/
'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
/*
* This array contains the hosts of which you want to allow incoming requests.
* Leave this empty if you want to accept requests from all hosts.
*/
'allowed_origins' => [
//
],
/*
* The maximum request size in kilobytes that is allowed for an incoming WebSocket request.
*/
'max_request_size_in_kb' => 250,
/*
* This path will be used to register the necessary routes for the package.
*/
'path' => 'laravel-websockets',
/*
* Dashboard Routes Middleware
*
* These middleware will be assigned to every dashboard route, giving you
* the chance to add your own middleware to this list or change any of
* the existing middleware. Or, you can simply stick with this list.
*/
'middleware' => [
'web',
Authorize::class,
],
'statistics' => [
/*
* This model will be used to store the statistics of the WebSocketsServer.
* The only requirement is that the model should extend
* `WebSocketsStatisticsEntry` provided by this package.
*/
'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
/**
* The Statistics Logger will, by default, handle the incoming statistics, store them
* and then release them into the database on each interval defined below.
*/
'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class,
/*
* Here you can specify the interval in seconds at which statistics should be logged.
*/
'interval_in_seconds' => 60,
/*
* When the clean-command is executed, all recorded statistics older than
* the number of days specified here will be deleted.
*/
'delete_statistics_older_than_days' => 60,
/*
* Use an DNS resolver to make the requests to the statistics logger
* default is to resolve everything to 127.0.0.1.
*/
'perform_dns_lookup' => false,
],
/*
* Define the optional SSL context for your WebSocket connections.
* You can see all available options at: http://php.net/manual/en/context.ssl.php
*/
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
/*
* Passphrase for your local_cert file.
*/
'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
],
/*
* Channel Manager
* This class handles how channel persistence is handled.
* By default, persistence is stored in an array by the running webserver.
* The only requirement is that the class should implement
* `ChannelManager` interface provided by this package.
*/
'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];
Docker撰写文件:Docker-compose.yml
version: '3'
services:
nginx:
build: ./docker/nginx
restart: always
command: ['nginx-debug', '-g', 'daemon off;']
volumes:
- ./:/app/
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- 80:80
- 443:443
depends_on:
- php
networks:
- internal
php:
build: ./
image: zagreus/melodi
container_name: zagreus-melodi
restart: always
working_dir: /app
command: [ "bash", "/app/docker/initialize.sh" ]
ports:
- 6001:6001
volumes:
- ./:/app/
- ./docker/php/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
depends_on:
- database
- redis
networks:
- internal
database:
image: mariadb
container_name: melodi-database
restart: always
environment:
- MARIADB_RANDOM_ROOT_PASSWORD=yes
- MARIADB_DATABASE=${DB_DATABASE:?DB_DATABASE not entered}
- MARIADB_USER=${DB_USERNAME:?DB_USERNAME not entered}
- MARIADB_PASSWORD=${DB_PASSWORD?DB_PASSWORD not entered}
volumes:
- ${DB_PERSIST_PATH:?DB_PERSIST_PATH not entered}:/var/lib/mysql
networks:
- internal
# ports:
# - 3306:3306
phpmyadmin:
image: phpmyadmin
container_name: melodi-phpmyadmin
restart: always
depends_on:
- database
ports:
- 8080:80
networks:
- internal
environment:
- PMA_HOST=database
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD:-password}
- PMA_ARBITRARY=1
- UPLOAD_LIMIT=2G
redis:
image: redis:7.0.0-bullseye
container_name: melodi-redis
restart: always
networks:
- internal
networks:
internal:
driver: bridge
感谢您给出这个问题的时间&lt; 3
I've set up my Laravel project with docker and docker-compose.
I've exposed port 6001, which is the port for running the WebSocket as default, and configured Nginx based on the documentation, but when I try to connect to my WS server using my domain, I get this error on the Nginx log file:
upstream prematurely closed connection while reading response header from upstream, client: *, server: site.cpm, request: "GET /app/7f0cb504a1426efd6854a03779a1c8a9?protocol=7&client=js&version=7.0.6&flash=false HTTP/1.1", upstream: "http://172.19.0.5:3030/app/7f0cb504a1426efd6854a03779a1c8a9?protocol=7&client=js&version=7.0.6&flash=false", host: "site.com"
Another weird problem is now I can't even connect to my WS server using direct IP and port.
I should also mention that there isn't any firewall activated on my server (at least, as far as I know).
Nginx config file:
map $http_upgrade $type {
default "web";
websocket "ws";
}
upstream websocket {
server php:6001;
}
server {
listen 80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /app/docker/nginx/certs/public-selfsigned.crt;
ssl_certificate_key /app/docker/nginx/certs/private-selfsigned.key;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
server_name panel.melodigram.app;
client_max_body_size 2048M;
index index.php index.html;
error_log /var/log/nginx/fpm.log;
access_log /var/log/nginx/access.log;
root /app/public_html;
location / {
try_files /nonexistent @$type;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location @web {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
location @ws {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
}
}
Websocet config: websockets.php
<?php
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;
return [
/*
* Set a custom dashboard configuration
*/
'dashboard' => [
'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
],
/*
* This package comes with multi tenancy out of the box. Here you can
* configure the different apps that can use the webSockets server.
*
* Optionally you specify capacity so you can limit the maximum
* concurrent connections for a specific app.
*
* Optionally you can disable client events so clients cannot send
* messages to each other via the webSockets.
*/
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
/*
* This class is responsible for finding the apps. The default provider
* will use the apps defined in this config file.
*
* You can create a custom provider by implementing the
* `AppProvider` interface.
*/
'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
/*
* This array contains the hosts of which you want to allow incoming requests.
* Leave this empty if you want to accept requests from all hosts.
*/
'allowed_origins' => [
//
],
/*
* The maximum request size in kilobytes that is allowed for an incoming WebSocket request.
*/
'max_request_size_in_kb' => 250,
/*
* This path will be used to register the necessary routes for the package.
*/
'path' => 'laravel-websockets',
/*
* Dashboard Routes Middleware
*
* These middleware will be assigned to every dashboard route, giving you
* the chance to add your own middleware to this list or change any of
* the existing middleware. Or, you can simply stick with this list.
*/
'middleware' => [
'web',
Authorize::class,
],
'statistics' => [
/*
* This model will be used to store the statistics of the WebSocketsServer.
* The only requirement is that the model should extend
* `WebSocketsStatisticsEntry` provided by this package.
*/
'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
/**
* The Statistics Logger will, by default, handle the incoming statistics, store them
* and then release them into the database on each interval defined below.
*/
'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class,
/*
* Here you can specify the interval in seconds at which statistics should be logged.
*/
'interval_in_seconds' => 60,
/*
* When the clean-command is executed, all recorded statistics older than
* the number of days specified here will be deleted.
*/
'delete_statistics_older_than_days' => 60,
/*
* Use an DNS resolver to make the requests to the statistics logger
* default is to resolve everything to 127.0.0.1.
*/
'perform_dns_lookup' => false,
],
/*
* Define the optional SSL context for your WebSocket connections.
* You can see all available options at: http://php.net/manual/en/context.ssl.php
*/
'ssl' => [
/*
* Path to local certificate file on filesystem. It must be a PEM encoded file which
* contains your certificate and private key. It can optionally contain the
* certificate chain of issuers. The private key also may be contained
* in a separate file specified by local_pk.
*/
'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
/*
* Path to local private key file on filesystem in case of separate files for
* certificate (local_cert) and private key.
*/
'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
/*
* Passphrase for your local_cert file.
*/
'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
],
/*
* Channel Manager
* This class handles how channel persistence is handled.
* By default, persistence is stored in an array by the running webserver.
* The only requirement is that the class should implement
* `ChannelManager` interface provided by this package.
*/
'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];
Docker compose file: docker-compose.yml
version: '3'
services:
nginx:
build: ./docker/nginx
restart: always
command: ['nginx-debug', '-g', 'daemon off;']
volumes:
- ./:/app/
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- 80:80
- 443:443
depends_on:
- php
networks:
- internal
php:
build: ./
image: zagreus/melodi
container_name: zagreus-melodi
restart: always
working_dir: /app
command: [ "bash", "/app/docker/initialize.sh" ]
ports:
- 6001:6001
volumes:
- ./:/app/
- ./docker/php/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
depends_on:
- database
- redis
networks:
- internal
database:
image: mariadb
container_name: melodi-database
restart: always
environment:
- MARIADB_RANDOM_ROOT_PASSWORD=yes
- MARIADB_DATABASE=${DB_DATABASE:?DB_DATABASE not entered}
- MARIADB_USER=${DB_USERNAME:?DB_USERNAME not entered}
- MARIADB_PASSWORD=${DB_PASSWORD?DB_PASSWORD not entered}
volumes:
- ${DB_PERSIST_PATH:?DB_PERSIST_PATH not entered}:/var/lib/mysql
networks:
- internal
# ports:
# - 3306:3306
phpmyadmin:
image: phpmyadmin
container_name: melodi-phpmyadmin
restart: always
depends_on:
- database
ports:
- 8080:80
networks:
- internal
environment:
- PMA_HOST=database
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD:-password}
- PMA_ARBITRARY=1
- UPLOAD_LIMIT=2G
redis:
image: redis:7.0.0-bullseye
container_name: melodi-redis
restart: always
networks:
- internal
networks:
internal:
driver: bridge
Thanks for the time which you give to this question <3
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的,所以我发现问题是即使我使用nginx作为反向代理,我的nginx本身正在处理SSL,我也填写了
laravel_websockets_sssl_local_cert_cert_cert
和laravel_weavel_websockets_sssl_local_local_local_pk
>在我的环境文件中引起问题。因此,如果您将NGINX用作反向代理,请确保在容器上打开端口后,只需让Nginx处理SSL,并且不要在此软件包上再次配置它。
Ok, so I found out that the problem was even though I was using Nginx as a reverse proxy and my Nginx was handling SSL by itself, I've also filled
LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT
andLARAVEL_WEBSOCKETS_SSL_LOCAL_PK
in my environment file that causes the problem.So if you are using Nginx as a reverse proxy, after making sure that the port is open on your container, just let Nginx handle the SSL and don't configure it again on this package.