Ten przewodnik pokazuje, jak skonfigurować aplikację Laravel w czasie rzeczywistym z użyciem Laravel Reverb (WebSockety) w środowisku produkcyjnym na Dockerze, na bazie sprawdzonej, produkcyjnej konfiguracji.
📋 Spis treści
- 🚀 Laravel Reverb z Dockerem: Przewodnik Produkcyjny
- 📋 Spis treści
- 1. Wstęp
- 2. Struktura projektu i docker-compose
- 3. Instalacja Reverb i konfiguracja Laravel
- 4. Konfiguracja środowiska (.env)
- 5. Konfiguracja proxy nginx
- 6. Wysyłanie eventów
- 7. Konfiguracja frontendu (Echo)
- 8. Przykład aktualizacji UI w czasie rzeczywistym
- 9. Checklist produkcyjny i rozwiązywanie problemów
- 10. Bezpieczeństwo produkcyjne: HTTPS i WSS
- 11. Podsumowanie
1. Wstęp
Laravel Reverb to oficjalny serwer WebSocket dla Laravel. Dzięki Dockerowi możesz uruchomić Reverb jako osobny serwis, przekierować ruch WebSocket przez nginx i korzystać z Laravel Echo na froncie do funkcji czasu rzeczywistego.
2. Struktura projektu i docker-compose
docker-compose.production.yml (fragmenty):
services:
app:
image: ...
container_name: laravel_app
# ...
networks:
- laravel_network
depends_on:
- redis
reverb:
image: ...
container_name: laravel_reverb
command: php artisan reverb:start --host=0.0.0.0 --port=8080 --debug
volumes:
- ./.env:/var/www/.env
ports:
- "6001:8080" # (opcjonalnie, do bezpośredniego dostępu)
depends_on:
- redis
networks:
- laravel_network
nginx:
image: ...
container_name: laravel_nginx
ports:
- '80:80'
- '443:443'
volumes:
- laravel_storage:/var/www/storage
networks:
- laravel_network
depends_on:
- app
- reverb
redis:
image: redis:alpine
container_name: laravel_redis
# ...
networks:
- laravel_network
networks:
laravel_network:
driver: bridge
volumes:
laravel_storage:
redis_data:
3. Instalacja Reverb i konfiguracja Laravel
- Zainstaluj Reverb i zależności Echo:
composer require laravel/reverb php artisan install:broadcasting npm install laravel-echo pusher-js
- Dodaj serwis reverb do docker-compose (patrz wyżej).
- Skonfiguruj broadcasting w Laravel:
W pliku
config/broadcasting.php
ustaw:'default' => env('BROADCAST_DRIVER', 'reverb'), ... 'connections' => [ 'reverb' => [ 'driver' => 'reverb', 'key' => env('REVERB_APP_KEY'), 'secret' => env('REVERB_APP_SECRET'), 'app_id' => env('REVERB_APP_ID'), 'host' => env('REVERB_HOST', 'reverb'), 'port' => env('REVERB_PORT', 8080), 'scheme' => env('REVERB_SCHEME', 'http'), ], ... ]
4. Konfiguracja środowiska (.env)
Backend (.env):
BROADCAST_DRIVER=reverb
REVERB_APP_ID=twoje_app_id
REVERB_APP_KEY=twoj_app_key
REVERB_APP_SECRET=twoj_app_secret
REVERB_HOST=reverb
REVERB_PORT=8080
REVERB_SCHEME=http
# Dla frontendu (Vite):
VITE_REVERB_APP_KEY=twoj_app_key
VITE_REVERB_HOST=twoja_domena_lub_ip
VITE_REVERB_PORT=80
VITE_REVERB_SCHEME=http
REVERB_HOST
musi odpowiadać nazwie serwisu w docker-compose (tu:reverb
).VITE_REVERB_HOST
to publiczna domena lub IP, pod którym frontend łączy się z WebSocketem.
5. Konfiguracja proxy nginx
docker/nginx/conf.d/default.conf (fragment):
server {
listen 80;
server_name _;
# ...
location /app {
proxy_pass http://reverb:8080;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
# ...
}
- To przekierowuje
/app
do kontenera reverb na porcie 8080. - Echo na froncie łączy się przez
/app
do Twojej domeny/IP.
6. Wysyłanie eventów
Przykład eventu:
// app/Events/ClickEvent.php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class ClickEvent implements ShouldBroadcast
{
use Dispatchable, SerializesModels;
public function broadcastOn(): Channel
{
return new Channel('clicks');
}
public function broadcastAs(): string
{
return 'Clicked';
}
}
Wywołanie eventu w kontrolerze:
// app/Http/Controllers/ClickController.php
public function click(Request $request)
{
Click::firstOrCreate()->increment('times');
event(new ClickEvent());
return redirect()->route('clicks.index');
}
7. Konfiguracja frontendu (Echo)
resources/js/echo.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST ?? window.location.hostname,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: import.meta.env.VITE_REVERB_SCHEME === 'https',
enabledTransports: ['ws'],
disableStats: true,
auth: {
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content')
}
}
});
8. Przykład aktualizacji UI w czasie rzeczywistym
Komponent React (Click.tsx):
import { useState, useEffect } from 'react';
export default function Click({ click }) {
const [times, setTimes] = useState(click?.times || 0);
useEffect(() => {
const channel = window.Echo.channel('clicks');
channel.listen('.Clicked', () => {
setTimes(prev => prev + 1); // Lub pobierz nową wartość z backendu
});
return () => {
window.Echo.leave('clicks');
};
}, []);
// ...obsługa kliknięcia/resetu...
}
- Dzięki temu UI aktualizuje się w czasie rzeczywistym u wszystkich użytkowników bez przeładowania strony.
9. Checklist produkcyjny i rozwiązywanie problemów
- REVERB_HOST w
.env
ustawiony na nazwę serwisu Docker (reverb
) - VITE_REVERB_HOST to Twoja publiczna domena/IP
- Nginx proxyfikuje
/app
do kontenera reverb - Wszystkie kontenery są w tej samej sieci Docker
- Po zmianie
.env
uruchomphp artisan config:clear
iphp artisan cache:clear
- Port WebSocket nie jest wystawiony publicznie (chyba że to konieczne)
- W produkcji używaj HTTPS dla bezpieczeństwa (patrz sekcja niżej)
- Sprawdzaj logi:
docker logs laravel_reverb
,docker logs laravel_nginx
,storage/logs/laravel.log
- Używaj
ShouldBroadcastNow
dla natychmiastowej dostawy eventów
Typowe problemy:
cURL error 7: Failed to connect to 0.0.0.0
– ustawREVERB_HOST
na nazwę serwisu Docker, nie0.0.0.0
.- WebSocket łączy się, ale nie ma eventów: sprawdź dispatch eventu, konfigurację broadcastingu i logi.
- WebSocket rozłącza się po 60s: zwiększ
proxy_read_timeout
w nginx.
10. Bezpieczeństwo produkcyjne: HTTPS i WSS
W środowisku produkcyjnym zawsze używaj HTTPS dla aplikacji i WSS (WebSocket Secure) dla połączeń WebSocket. Dzięki temu cała komunikacja między użytkownikiem a serwerem jest szyfrowana i bezpieczna.
Jak włączyć HTTPS/WSS:
- Uzyskaj certyfikaty SSL (np. Let's Encrypt) i umieść je w kontenerze nginx (np.
docker/nginx/ssl/
). - Zaktualizuj konfigurację nginx, aby nasłuchiwał na porcie 443 i używał SSL:
server {
listen 443 ssl;
server_name twojadomena.pl;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# ...
location /app {
proxy_pass http://reverb:8080;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
# ...
}
- Zmapuj certyfikaty SSL w docker-compose:
nginx:
# ...
volumes:
- ./docker/nginx/ssl:/etc/nginx/ssl:ro
- Zaktualizuj .env dla frontendu:
VITE_REVERB_SCHEME=https
VITE_REVERB_PORT=443
- Zaktualizuj konfigurację Echo:
window.Echo = new Echo({
// ...
forceTLS: true, // lub: import.meta.env.VITE_REVERB_SCHEME === 'https',
wsPort: 80,
wssPort: 443,
// ...
});
- W nginx ustaw przekierowanie z HTTP na HTTPS dla pełnego bezpieczeństwa.
Checklist:
- Certyfikaty SSL są poprawne i zmapowane do nginx
- Nginx nasłuchuje na 443 i proxyfikuje
/app
jak wcześniej -
VITE_REVERB_SCHEME=https
iforceTLS: true
w konfiguracji Echo - Frontend łączy się przez
wss://twojadomena.pl/app/...
Uwaga:
Przeglądarki blokują połączenia
ws://
(nieszyfrowane WebSockety) z aplikacji ładowanej przezhttps://
. W produkcji zawsze używajwss://
!
11. Podsumowanie
Z tą konfiguracją masz gotową, produkcyjną aplikację Laravel z WebSocketami (Reverb) na Dockerze. Możesz broadcastować eventy i aktualizować frontend w czasie rzeczywistym dla wszystkich użytkowników.
Więcej porad Laravel & DevOps: Dominik Jasiński na LinkedIn