Правки локального размещения дева, перенос тунеля в контейнер

This commit is contained in:
2026-06-17 04:27:11 +03:00
parent b04fbb2e17
commit 7e8b748caf
14 changed files with 249 additions and 152 deletions
+46 -34
View File
@@ -1,26 +1,27 @@
#!/usr/bin/env pwsh
# ╔═══════════════════════════════════════════════════════════════════════════╗
# ║ Единый лаунчер dev / test. APP_ENV из корневого .env решает, что запускать. ║
# ╚═══════════════════════════════════════════════════════════════════════════╝
# development → uvicorn --reload (бэк) + vite (фронт), нативно, в двух окнах
# test → docker compose прод-клон (порт 8080)
# production → лаунчером НЕ запускается (прод обособлен: docker compose up -d на Pi)
# Unified launcher for dev / test. APP_ENV in the root .env decides what to run.
# development -> uvicorn --reload (backend) + vite (frontend), native, two windows
# test -> docker compose prod-clone (port 8080)
# production -> NOT started by launcher (prod is separate: docker compose up -d on Pi)
#
# LOCAL_PUBLIC=vps дополнительно поднимает SSH-туннель на VPS, и dev/test становится
# виден снаружи на https://forbidden-stars.ru (нужен настроенный VPS, см. deploy/vps).
# LOCAL_PUBLIC=vps (dev only) opens an SSH tunnel to the VPS, exposing dev at
# https://forbidden-stars.ru. test/prod expose themselves via an in-container tunnel.
#
# Запуск: .\run.ps1
# Если ругается на политику: Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
# Run: .\run.ps1
# If blocked by policy: Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
#
# NOTE: keep this file ASCII-only. Windows PowerShell 5.1 reads BOM-less .ps1 in the
# system ANSI codepage, so non-ASCII (Cyrillic / box chars) breaks the parser.
$ErrorActionPreference = "Stop"
$root = $PSScriptRoot
$envFile = Join-Path $root ".env"
if (-not (Test-Path $envFile)) {
Write-Host "Нет .env в корне. Скопируйте: Copy-Item .env.example .env" -ForegroundColor Red
Write-Host "No .env in repo root. Create it: Copy-Item .env.example .env" -ForegroundColor Red
exit 1
}
# Достаём значение ключа из .env (последнее присвоение побеждает; комментарии игнор).
# Read a key from .env (last assignment wins; comments ignored).
function Get-EnvVal([string]$name, [string]$default) {
$val = $default
foreach ($line in Get-Content $envFile) {
@@ -37,37 +38,51 @@ $vpsPort = Get-EnvVal "VPS_TUNNEL_PORT" "9001"
Write-Host "APP_ENV = $appEnv LOCAL_PUBLIC = $localPublic" -ForegroundColor Cyan
# Поднимает SSH reverse-tunnel: VPS:$vpsPort → localhost:$localPort (в отдельном окне).
# Open SSH reverse tunnel VPS:$vpsPort -> localhost:$localPort (in a separate window).
function Start-VpsTunnel([int]$localPort) {
if (-not $vpsHost) {
Write-Host "LOCAL_PUBLIC=vps, но VPS_TUNNEL_HOST не задан в .env — туннель пропущен." -ForegroundColor Red
Write-Host "LOCAL_PUBLIC=vps but VPS_TUNNEL_HOST is empty in .env - tunnel skipped." -ForegroundColor Red
return
}
Write-Host "SSH-туннель: forbidden-stars.ru (VPS:$vpsPort) → localhost:$localPort …" -ForegroundColor Green
Write-Host "SSH tunnel: forbidden-stars.ru (VPS:$vpsPort) -> localhost:$localPort ..." -ForegroundColor Green
$ssh = "ssh -N -R ${vpsPort}:localhost:${localPort} " +
"-o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes " +
"${vpsUser}@${vpsHost}"
Start-Process powershell -ArgumentList @(
"-NoExit", "-Command",
"Write-Host 'SSH-туннель на forbidden-stars.ru. Закрой окно, чтобы остановить.' -ForegroundColor Cyan; $ssh"
"Write-Host 'SSH tunnel to forbidden-stars.ru. Close this window to stop.' -ForegroundColor Cyan; $ssh"
)
}
# Kill any leftover tunnel from a previous run, so LOCAL_PUBLIC is authoritative each launch
# (the tunnel lives in its own window and would otherwise keep the domain served).
function Stop-VpsTunnel {
Get-CimInstance Win32_Process -Filter "Name='ssh.exe'" -ErrorAction SilentlyContinue |
Where-Object { $_.CommandLine -match "-R\s+${vpsPort}:localhost" } |
ForEach-Object {
Write-Host "Closing leftover tunnel (pid $($_.ProcessId))..." -ForegroundColor DarkYellow
Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue
}
}
# Start from a clean tunnel state; a fresh tunnel is opened only if LOCAL_PUBLIC=vps below.
Stop-VpsTunnel
switch ($appEnv) {
"development" {
$backend = Join-Path $root "backend"
$frontend = Join-Path $root "frontend"
$py = Join-Path $backend ".venv\Scripts\python.exe"
if (-not (Test-Path $py)) {
Write-Host "Нет venv: $py" -ForegroundColor Red
Write-Host "Сначала: cd backend; python -m venv .venv; .\.venv\Scripts\Activate.ps1; pip install -e `".[dev]`"" -ForegroundColor Yellow
Write-Host "venv not found: $py" -ForegroundColor Red
Write-Host "First: cd backend; python -m venv .venv; .\.venv\Scripts\Activate.ps1; pip install -e `".[dev]`"" -ForegroundColor Yellow
exit 1
}
if (-not (Test-Path (Join-Path $frontend "node_modules"))) {
Write-Host "Нет node_modules. Сначала: cd frontend; npm install" -ForegroundColor Red
Write-Host "node_modules not found. First: cd frontend; npm install" -ForegroundColor Red
exit 1
}
Write-Host "Запуск бэка (uvicorn --reload) и фронта (vite) в отдельных окнах…" -ForegroundColor Green
Write-Host "Starting backend (uvicorn --reload) and frontend (vite) in separate windows..." -ForegroundColor Green
Start-Process powershell -ArgumentList @(
"-NoExit", "-Command",
"Set-Location '$backend'; & '$py' -m uvicorn app.main:app --reload"
@@ -77,34 +92,31 @@ switch ($appEnv) {
"Set-Location '$frontend'; npm run dev"
)
Write-Host ""
Write-Host " Бэк: http://127.0.0.1:8000 (Swagger: /api/docs)" -ForegroundColor Green
Write-Host " Фронт: http://127.0.0.1:5173" -ForegroundColor Green
Write-Host " Backend: http://127.0.0.1:8000 (Swagger: /api/docs)" -ForegroundColor Green
Write-Host " Frontend: http://127.0.0.1:5173" -ForegroundColor Green
if ($localPublic -eq "vps") {
Start-VpsTunnel 5173
Write-Host " Публично: https://forbidden-stars.ru" -ForegroundColor Green
Write-Host " Public: https://forbidden-stars.ru" -ForegroundColor Green
}
}
"test" {
$compose = Join-Path $root "docker-compose.test.yml"
Write-Host "Сборка и запуск прод-клона в Docker (порт 8080)…" -ForegroundColor Green
Write-Host "Building and starting prod-clone in Docker (app + in-container tunnel)..." -ForegroundColor Green
docker compose -f $compose up --build -d
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
Write-Host ""
Write-Host " Открыть: http://localhost:8080 (Swagger: /api/docs)" -ForegroundColor Green
Write-Host " Логи: docker compose -f docker-compose.test.yml logs -f"
Write-Host " Стоп: docker compose -f docker-compose.test.yml down -v"
if ($localPublic -eq "vps") {
Start-VpsTunnel 8080
Write-Host " Публично: https://forbidden-stars.ru" -ForegroundColor Green
}
Write-Host " Public: https://forbidden-stars.ru (Swagger: /api/docs)" -ForegroundColor Green
Write-Host " (no host port - reachable only via the domain; tunnel runs inside compose)"
Write-Host " Logs: docker compose -f docker-compose.test.yml logs -f"
Write-Host " Stop: docker compose -f docker-compose.test.yml down -v"
}
"production" {
Write-Host "production лаунчером не запускается — прод обособлен." -ForegroundColor Yellow
Write-Host "Деплой на Pi (из ветки main): docker compose up -d --build"
Write-Host "production is not started by the launcher - prod is separate." -ForegroundColor Yellow
Write-Host "Deploy on Pi (from main branch): docker compose up -d --build"
exit 1
}
default {
Write-Host "Неизвестный APP_ENV='$appEnv'. Допустимо: development | test | production." -ForegroundColor Red
Write-Host "Unknown APP_ENV='$appEnv'. Allowed: development | test | production." -ForegroundColor Red
exit 1
}
}