build: panel w osobnym kontenerze za nginxem

Rozdzielenie na dwie niezależne usługi:

- frontend/Dockerfile buduje panel w etapie node:22-alpine, a artefakt
  serwuje nginx:1.27-alpine. Obraz nie zawiera Node'a ani źródeł.
- frontend/nginx.conf serwuje aplikację jednostronicową (nieznane ścieżki
  wracają jako index.html), cache'uje /assets z sumą kontrolną w nazwie,
  a /api i /ws przekazuje do usługi discord-bot. Przeglądarka widzi jedno
  źródło, więc backend nie potrzebuje CORS-u.
  Adres backendu siedzi w zmiennej nginxa, więc nazwa jest rozwiązywana
  przy żądaniu i panel wstaje niezależnie od kolejności startu kontenerów.
- Proxy nie limituje rozmiaru ciała żądania i nie buforuje go, żeby
  wysyłka dużych plików wideo/audio przechodziła bez zmian w backendzie.
  Timeouty podniesione, bo panel trzyma WebSocket otwarty na stałe.
- Root Dockerfile wraca do samego Pythona i wystawia port 8000.
- compose.yaml uruchamia obie usługi we wspólnej sieci: panel na :80,
  API na :8000 (wystawione do diagnostyki).
- Katalog static/ znika z repozytorium - nie ma już czego serwować.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
lgooseandClaude Bot committed 2026-08-21 01:08:50 +02:00
1 parent 8d32d5afc6
commit bbd8a321f4
7 files changed
+124 -11

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
node_modules/
dist/
*.tsbuildinfo
README.md
+22
View File
@@ -0,0 +1,22 @@
# --- Etap 1: budowa panelu ---------------------------------------------------
FROM node:22-alpine AS build
WORKDIR /app
# Zależności instalujemy przed skopiowaniem źródeł, aby korzystać z cache warstw.
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# --- Etap 2: serwowanie przez nginx ------------------------------------------
FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
CMD wget -qO- http://localhost/ >/dev/null || exit 1
+51
View File
@@ -0,0 +1,51 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Nazwa usługi backendu z compose.yaml; zmienna wymusza rozwiązywanie DNS
# w czasie żądania, więc nginx wstaje nawet gdy bot jeszcze się nie podniósł.
resolver 127.0.0.11 valid=10s ipv6=off;
set $backend "http://discord-bot:8000";
# Aplikacja jednostronicowa - nieznane ścieżki oddajemy index.html.
location / {
try_files $uri $uri/ /index.html;
}
# Artefakty Vite mają skrót treści w nazwie, więc można je cache'ować na stałe.
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
location /api/ {
proxy_pass $backend;
proxy_http_version 1.1;
proxy_set_header Host $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;
# Wysyłanie plików wideo/audio na serwer - bez limitu rozmiaru.
client_max_body_size 0;
proxy_request_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /ws {
proxy_pass $backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
# Panel trzyma połączenie otwarte i odbiera stan raz na sekundę.
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}