🚀 Laravel Reverb z Dockerem: Przewodnik Produkcyjny

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


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

  1. Zainstaluj Reverb i zależności Echo:
    composer require laravel/reverb
    php artisan install:broadcasting
    npm install laravel-echo pusher-js
    
  2. Dodaj serwis reverb do docker-compose (patrz wyżej).
  3. 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 uruchom php artisan config:clear i php 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 – ustaw REVERB_HOST na nazwę serwisu Docker, nie 0.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:

  1. Uzyskaj certyfikaty SSL (np. Let's Encrypt) i umieść je w kontenerze nginx (np. docker/nginx/ssl/).
  2. 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";
    }
    # ...
}
  1. Zmapuj certyfikaty SSL w docker-compose:
nginx:
  # ...
  volumes:
    - ./docker/nginx/ssl:/etc/nginx/ssl:ro
  1. Zaktualizuj .env dla frontendu:
VITE_REVERB_SCHEME=https
VITE_REVERB_PORT=443
  1. Zaktualizuj konfigurację Echo:
window.Echo = new Echo({
    // ...
    forceTLS: true, // lub: import.meta.env.VITE_REVERB_SCHEME === 'https',
    wsPort: 80,
    wssPort: 443,
    // ...
});
  1. 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 i forceTLS: true w konfiguracji Echo
  • Frontend łączy się przez wss://twojadomena.pl/app/...

Uwaga:

Przeglądarki blokują połączenia ws:// (nieszyfrowane WebSockety) z aplikacji ładowanej przez https://. W produkcji zawsze używaj wss://!


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

Komentarze (0)
Zostaw komentarz

© 2025 Wszelkie prawa zastrzeżone.