Laravel 12 WebSocket (Reverb) 容器化全攻略:Nginx 反向代理實戰
1. 專案架構概覽
在 Docker 環境中,我們將流量分為兩路:
HTTP 請求 → 轉發至
app容器 (PHP-FPM)。WebSocket 請求 → 轉發至
reverb容器 (Laravel 官方 WebSocket Server)。
Nginx 站在最前端作為唯一入口,負責處理 TLS 終止(若有)與 WebSocket 的協議升級(Protocol Upgrade)。
目錄結構建議
laravel-project/
├── docker-compose.yml
├── Dockerfile
├── .env
├── nginx/
│ └── default.conf # Nginx 反向代理設定
├── resources/js/echo.js # 前端 Echo 配置
└── app/Events/MessageSent.php # 廣播事件範例
2. Nginx 配置:協議升級 (nginx/default.conf)
WebSocket 連線必須正確處理 Upgrade 與 Connection 標頭。
server {
listen 80;
server_name localhost;
root /var/www/html/public;
index index.php;
# WebSocket 請求 (Reverb 預設路徑 /app)
location /app {
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 核心:允許協議升級
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_read_timeout 86400s; # 防止長連線被切斷
proxy_pass http://reverb:8080;
}
# Laravel 一般 HTTP 請求
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
3. Docker 編排:docker-compose.yml
定義四個服務,確保 Reverb 與 App 共用同一份程式碼與 Redis 驅動。
services:
app:
build: .
container_name: laravel-app
volumes:
- .:/var/www/html
depends_on:
- redis
reverb:
build: .
container_name: laravel-reverb
command: php artisan reverb:start --host=0.0.0.0 --port=8080
volumes:
- .:/var/www/html
depends_on:
- app
nginx:
image: nginx:alpine
container_name: laravel-nginx
ports:
- "80:80"
volumes:
- .:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
- reverb
redis:
image: redis:alpine
4. 前端配置:Laravel Echo (resources/js/echo.js)
Laravel 12 的 Echo 透過 Vite 環境變數讀取設定,並透過 Nginx 轉發。
import Echo from 'laravel-echo';
import Pusher from 'pusher-js'; // Reverb 仍使用 Pusher 協定
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
5. 環境變數設定 (.env)
區分容器間通訊(後端)與瀏覽器連線(前端)。
BROADCAST_CONNECTION=reverb
QUEUE_CONNECTION=redis
# 後端 (PHP 容器連向 Reverb 容器)
REVERB_HOST=reverb
REVERB_PORT=8080
# 前端 (瀏覽器連向 Nginx)
VITE_REVERB_APP_KEY=my-reverb-key
VITE_REVERB_HOST=localhost
VITE_REVERB_PORT=80
VITE_REVERB_SCHEME=http
6. Dockerfile 核心優化
確保安裝 pcntl 擴充,這是 Reverb 處理併發連線所必須的。
FROM php:8.3-fpm
RUN apt-get update && apt-get install -y \
libpng-dev zip unzip git curl
# 安裝必要 PHP 擴充
RUN docker-php-ext-install pdo_mysql pcntl bcmath
WORKDIR /var/www/html
# 修正權限
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
7. 部署與驗證步驟
安裝依賴:
composer install && npm install && npm run build啟動容器:
docker compose up -d檢查連線: * 開啟瀏覽器 F12 → Network → WS 標籤。
看到連往
ws://localhost/app/...的請求。狀態碼應顯示 101 Switching Protocols。
8. 常見排錯檢查清單
連線被拒: 檢查
nginx/default.conf中的proxy_pass是否正確指向服務名reverb。廣播沒反應: 確保有容器在執行
php artisan queue:work,因為廣播通常是非同步的。權限問題: 確保 Docker 中的
storage目錄對www-data使用者是可寫入的。
這套架構讓你在移除所有手動操作的同時,獲得了極高的可擴充性與穩定性,非常適合現代 Laravel 開發。
沒有留言:
張貼留言