From dcdd1f68988d3e08b15164f289953e5a3d1654eb Mon Sep 17 00:00:00 2001 From: test2 Date: Sat, 25 Jul 2026 20:48:13 +0300 Subject: [PATCH] Fix postgres DNS: put both services on dokploy-network Co-authored-by: Cursor --- README.md | 11 ++++------- docker-compose.yml | 18 +++++++++-------- scripts/entrypoint.sh | 45 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 3785e61..7551e8d 100644 --- a/README.md +++ b/README.md @@ -44,13 +44,10 @@ POSTGRES_PASSWORD=надежный-пароль-бд 1. В Dokploy Domain укажите сервис **`panel`**, порт **`8000`** (не `postgres`). 2. Откройте логи сервиса `panel` — должны быть строки `Database is ready` и `Starting uvicorn`. -3. Задайте `DATABASE_URL` явно, если пароль БД содержит спецсимволы: - -```env -DATABASE_URL=postgresql+asyncpg://vpn:ПАРОЛЬ@postgres:5432/vpn_panel -POSTGRES_PASSWORD=ПАРОЛЬ -``` - +3. Ошибка `Name or service not known` значит `panel` не видит хост БД: + - оба сервиса должны быть в сети `dokploy-network` (уже в compose); + - на сервере один раз: `docker network create dokploy-network` (Dokploy обычно создаёт сам); + - если сервис БД называется иначе — задайте `POSTGRES_HOST=<имя сервиса>`. 4. Redeploy после правок. Админ при каждом старте **синхронизируется из ENV**. diff --git a/docker-compose.yml b/docker-compose.yml index 58ece4c..7f68e93 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ services: - # IMPORTANT for Dokploy: attach domain to this service, port 8000 + # Domain in Dokploy → service `panel`, port `8000` panel: build: context: . @@ -22,10 +22,11 @@ services: ADMIN_PASSWORD: ${ADMIN_PASSWORD:-change-me-strong-password} ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com} + POSTGRES_HOST: ${POSTGRES_HOST:-postgres} POSTGRES_USER: ${POSTGRES_USER:-vpn} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-vpn} POSTGRES_DB: ${POSTGRES_DB:-vpn_panel} - DATABASE_URL: ${DATABASE_URL:-postgresql+asyncpg://vpn:vpn@postgres:5432/vpn_panel} + POSTGRES_PORT: ${POSTGRES_PORT:-5432} PUBLIC_HOST: ${PUBLIC_HOST:-127.0.0.1} PUBLIC_PORT: ${PUBLIC_PORT:-51820} @@ -43,13 +44,13 @@ services: - wg_data:/data/wireguard - awg_data:/data/amneziawg networks: - - vpn_net + - dokploy-network healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"] interval: 15s timeout: 5s retries: 10 - start_period: 90s + start_period: 120s postgres: image: postgres:16-alpine @@ -61,16 +62,17 @@ services: volumes: - postgres_data:/var/lib/postgresql/data networks: - - vpn_net + - dokploy-network healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] interval: 5s timeout: 5s - retries: 10 + retries: 20 + start_period: 10s networks: - vpn_net: - driver: bridge + dokploy-network: + external: true volumes: postgres_data: diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index f08dd60..16deb4f 100644 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -3,19 +3,50 @@ set -e echo "==> VpnPanel starting" -# Always build DATABASE_URL from POSTGRES_* (Dokploy-friendly) +DB_HOST="${POSTGRES_HOST:-postgres}" +DB_PORT="${POSTGRES_PORT:-5432}" +DB_USER="${POSTGRES_USER:-vpn}" +DB_PASS="${POSTGRES_PASSWORD:-vpn}" +DB_NAME="${POSTGRES_DB:-vpn_panel}" + export DATABASE_URL="$( + POSTGRES_HOST="$DB_HOST" \ + POSTGRES_PORT="$DB_PORT" \ + POSTGRES_USER="$DB_USER" \ + POSTGRES_PASSWORD="$DB_PASS" \ + POSTGRES_DB="$DB_NAME" \ python - <<'PY' import os from urllib.parse import quote_plus -user = os.environ.get("POSTGRES_USER", "vpn") -password = os.environ.get("POSTGRES_PASSWORD", "vpn") -db = os.environ.get("POSTGRES_DB", "vpn_panel") -print(f"postgresql+asyncpg://{quote_plus(user)}:{quote_plus(password)}@postgres:5432/{db}") +host = os.environ["POSTGRES_HOST"] +port = os.environ["POSTGRES_PORT"] +user = os.environ["POSTGRES_USER"] +password = os.environ["POSTGRES_PASSWORD"] +db = os.environ["POSTGRES_DB"] +print( + f"postgresql+asyncpg://{quote_plus(user)}:{quote_plus(password)}" + f"@{host}:{port}/{db}" +) PY )" +echo "DB target: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}" + +echo "DNS check..." +python - <<'PY' +import os +import socket + +host = os.environ.get("POSTGRES_HOST", "postgres") +try: + infos = socket.getaddrinfo(host, None) + addrs = sorted({i[4][0] for i in infos}) + print(f"Resolved {host} -> {', '.join(addrs)}") +except Exception as exc: # noqa: BLE001 + print(f"WARNING: cannot resolve '{host}': {exc}") +PY + echo "Waiting for database..." python - <<'PY' import asyncio @@ -38,9 +69,11 @@ async def wait_db(retries: int = 60) -> None: return except Exception as exc: # noqa: BLE001 print(f"DB not ready ({i + 1}/{retries}): {exc}") - await asyncio.sleep(1) + await asyncio.sleep(2) await engine.dispose() print("ERROR: database did not become ready", file=sys.stderr) + print("HINT: both panel and postgres must be on dokploy-network", file=sys.stderr) + print("HINT: in Dokploy set POSTGRES_HOST if DB service name differs", file=sys.stderr) sys.exit(1)