diff --git a/Dockerfile b/Dockerfile index 052998e..8f3f2fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,35 +1,31 @@ -# --- Etap 1: budowa panelu --------------------------------------------------- -FROM node:22-alpine AS frontend-build - +# --- Frontend build --------------------------------------------------------- +FROM node:22-alpine AS frontend-deps WORKDIR /frontend - COPY frontend/package.json frontend/package-lock.json ./ RUN npm ci +FROM frontend-deps AS frontend-build COPY frontend/ ./ RUN npm run build -# --- Etap 2: aplikacja ------------------------------------------------------- -FROM python:3.13-slim - -# Zależności systemowe: opus dla głosu, ffmpeg do dekodowania audio -RUN apt-get update && apt-get install -y \ - libopus0 \ - libopus-dev \ - ffmpeg \ - build-essential \ +# --- Python base ------------------------------------------------------------ +FROM python:3.13-slim AS python-base +RUN apt-get update && apt-get install -y --no-install-recommends \ + libopus0 ffmpeg \ && rm -rf /var/lib/apt/lists/* - WORKDIR /app - -# Zależności przed źródłami, aby korzystać z cache warstw. -COPY requirements.txt . +COPY requirements.txt ./requirements.txt RUN pip install --no-cache-dir -r requirements.txt +# --- Development ------------------------------------------------------------ +FROM python-base AS dev +RUN pip install --no-cache-dir ruff pytest +EXPOSE 8000 +CMD ["python", "-u", "main.py"] + +# --- Production ------------------------------------------------------------- +FROM python-base AS prod COPY . . COPY --from=frontend-build /frontend/dist /app/static - EXPOSE 8000 - -# Python serwuje API oraz zbudowany panel webowy. CMD ["python", "-u", "main.py"] diff --git a/README.md b/README.md index 4c89cfa..2966470 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,34 @@ Wymagane zmienne środowiskowe (plik `.env`): | `POSTGRES_PASSWORD` | Hasło użytkownika bazy; domyślnie `zyrarbot`, zalecana zmiana w `.env`. | | `POSTGRES_DB` / `POSTGRES_USER` | Opcjonalna nazwa bazy i użytkownika; domyślnie `zyrarbot`. | -Panel działa pod `http://localhost:8000` podczas uruchomienia lokalnego. W Dockerze -jest dostępny pod `http://localhost` po wykonaniu `docker compose up --build`. +Panel działa pod `http://localhost:8000` podczas uruchomienia lokalnego. + +### Docker: development i production + +Środowisko deweloperskie uruchom poleceniem: + +```bash +docker compose up --build +``` + +Kod Pythona jest montowany z katalogu projektu; po zmianach zrestartuj backend +poleceniem `docker compose restart discord-bot`. Frontend działa w osobnym +kontenerze i przebudowuje `frontend/dist` w trybie watch. Python serwuje ten sam +współdzielony katalog pod `http://localhost`. Port PostgreSQL `5432` jest +dostępny lokalnie. Obraz dev zawiera też Ruff, a kontener frontendu instaluje +narzędzia z `package-lock.json` (ESLint i `vue-tsc`). +Sprawdzenia uruchom w kontenerze backendu, np. `docker compose exec discord-bot +ruff check .` i `docker compose exec discord-bot pytest`; dla frontendu użyj +`docker compose exec frontend npm run lint` lub `npm run typecheck`. + +Production uruchom z pliku `compose.prod.yaml`: + +```bash +docker compose -f compose.prod.yaml up --build -d +``` + +W tym wariancie frontend jest budowany podczas tworzenia obrazu, a port PostgreSQL +nie jest publikowany na hoście. Panel obsługuje wiele serwerów Discorda. Wybór serwera w nagłówku przełącza jego osobną kolejkę, historię, bazę plików i ustawienia odtwarzania. Ustawienia, historia diff --git a/compose.prod.yaml b/compose.prod.yaml new file mode 100644 index 0000000..d33dffa --- /dev/null +++ b/compose.prod.yaml @@ -0,0 +1,43 @@ +services: + database: + image: postgres:17-alpine + environment: + POSTGRES_DB: ${POSTGRES_DB:-zyrarbot} + POSTGRES_USER: ${POSTGRES_USER:-zyrarbot} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-zyrarbot} + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 5s + retries: 10 + start_period: 10s + restart: unless-stopped + discord-bot: + build: + context: . + dockerfile: Dockerfile + target: prod + container_name: zyrarbot + environment: + - DISCORD_TOKEN=${DISCORD_TOKEN} + - GUILD_ID=${GUILD_ID:-} + - POSTGRES_DB=${POSTGRES_DB:-zyrarbot} + - POSTGRES_USER=${POSTGRES_USER:-zyrarbot} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-zyrarbot} + - POSTGRES_HOST=database + - POSTGRES_PORT=5432 + - PYTHONUNBUFFERED=1 + depends_on: + database: + condition: service_healthy + volumes: + - ./config:/app/config + - ./uploads:/app/uploads + ports: + - "80:8000" + restart: unless-stopped + +volumes: + postgres_data: diff --git a/compose.yaml b/compose.yaml index 0a442cb..abc8d2d 100644 --- a/compose.yaml +++ b/compose.yaml @@ -15,29 +15,46 @@ services: start_period: 10s restart: unless-stopped ports: - - "5432:5432/tcp" + - "5432:5432" discord-bot: build: context: . dockerfile: Dockerfile - container_name: zyrarbot + target: dev environment: - - DISCORD_TOKEN=${DISCORD_TOKEN} - - GUILD_ID=${GUILD_ID:-} - - POSTGRES_DB=${POSTGRES_DB:-zyrarbot} - - POSTGRES_USER=${POSTGRES_USER:-zyrarbot} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-zyrarbot} - - POSTGRES_HOST=database - - POSTGRES_PORT=5432 - - PYTHONUNBUFFERED=1 + DISCORD_TOKEN: ${DISCORD_TOKEN} + GUILD_ID: ${GUILD_ID:-} + POSTGRES_DB: ${POSTGRES_DB:-zyrarbot} + POSTGRES_USER: ${POSTGRES_USER:-zyrarbot} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-zyrarbot} + POSTGRES_HOST: database + POSTGRES_PORT: 5432 + PYTHONUNBUFFERED: 1 depends_on: database: condition: service_healthy volumes: + - .:/app - ./config:/app/config - ./uploads:/app/uploads + - ./frontend/dist:/app/static ports: - - "80:8000" + - "8000:8000" + restart: unless-stopped + frontend: + build: + context: . + dockerfile: Dockerfile + target: frontend-deps + working_dir: /frontend + command: + - sh + - -c + - test -x node_modules/.bin/vite || npm ci; exec npx vite build --watch + volumes: + - ./frontend:/frontend + environment: + VITE_BACKEND_URL: http://discord-bot:8000 restart: unless-stopped volumes: