Fix postgres DNS: put both services on dokploy-network
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -44,13 +44,10 @@ POSTGRES_PASSWORD=надежный-пароль-бд
|
|||||||
|
|
||||||
1. В Dokploy Domain укажите сервис **`panel`**, порт **`8000`** (не `postgres`).
|
1. В Dokploy Domain укажите сервис **`panel`**, порт **`8000`** (не `postgres`).
|
||||||
2. Откройте логи сервиса `panel` — должны быть строки `Database is ready` и `Starting uvicorn`.
|
2. Откройте логи сервиса `panel` — должны быть строки `Database is ready` и `Starting uvicorn`.
|
||||||
3. Задайте `DATABASE_URL` явно, если пароль БД содержит спецсимволы:
|
3. Ошибка `Name or service not known` значит `panel` не видит хост БД:
|
||||||
|
- оба сервиса должны быть в сети `dokploy-network` (уже в compose);
|
||||||
```env
|
- на сервере один раз: `docker network create dokploy-network` (Dokploy обычно создаёт сам);
|
||||||
DATABASE_URL=postgresql+asyncpg://vpn:ПАРОЛЬ@postgres:5432/vpn_panel
|
- если сервис БД называется иначе — задайте `POSTGRES_HOST=<имя сервиса>`.
|
||||||
POSTGRES_PASSWORD=ПАРОЛЬ
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Redeploy после правок.
|
4. Redeploy после правок.
|
||||||
|
|
||||||
Админ при каждом старте **синхронизируется из ENV**.
|
Админ при каждом старте **синхронизируется из ENV**.
|
||||||
|
|||||||
+10
-8
@@ -1,5 +1,5 @@
|
|||||||
services:
|
services:
|
||||||
# IMPORTANT for Dokploy: attach domain to this service, port 8000
|
# Domain in Dokploy → service `panel`, port `8000`
|
||||||
panel:
|
panel:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
@@ -22,10 +22,11 @@ services:
|
|||||||
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-change-me-strong-password}
|
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-change-me-strong-password}
|
||||||
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}
|
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}
|
||||||
|
|
||||||
|
POSTGRES_HOST: ${POSTGRES_HOST:-postgres}
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-vpn}
|
POSTGRES_USER: ${POSTGRES_USER:-vpn}
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-vpn}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-vpn}
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-vpn_panel}
|
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_HOST: ${PUBLIC_HOST:-127.0.0.1}
|
||||||
PUBLIC_PORT: ${PUBLIC_PORT:-51820}
|
PUBLIC_PORT: ${PUBLIC_PORT:-51820}
|
||||||
@@ -43,13 +44,13 @@ services:
|
|||||||
- wg_data:/data/wireguard
|
- wg_data:/data/wireguard
|
||||||
- awg_data:/data/amneziawg
|
- awg_data:/data/amneziawg
|
||||||
networks:
|
networks:
|
||||||
- vpn_net
|
- dokploy-network
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"]
|
test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"]
|
||||||
interval: 15s
|
interval: 15s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
start_period: 90s
|
start_period: 120s
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
@@ -61,16 +62,17 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
networks:
|
networks:
|
||||||
- vpn_net
|
- dokploy-network
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 20
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
vpn_net:
|
dokploy-network:
|
||||||
driver: bridge
|
external: true
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
|||||||
+39
-6
@@ -3,19 +3,50 @@ set -e
|
|||||||
|
|
||||||
echo "==> VpnPanel starting"
|
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="$(
|
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'
|
python - <<'PY'
|
||||||
import os
|
import os
|
||||||
from urllib.parse import quote_plus
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
user = os.environ.get("POSTGRES_USER", "vpn")
|
host = os.environ["POSTGRES_HOST"]
|
||||||
password = os.environ.get("POSTGRES_PASSWORD", "vpn")
|
port = os.environ["POSTGRES_PORT"]
|
||||||
db = os.environ.get("POSTGRES_DB", "vpn_panel")
|
user = os.environ["POSTGRES_USER"]
|
||||||
print(f"postgresql+asyncpg://{quote_plus(user)}:{quote_plus(password)}@postgres:5432/{db}")
|
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
|
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..."
|
echo "Waiting for database..."
|
||||||
python - <<'PY'
|
python - <<'PY'
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -38,9 +69,11 @@ async def wait_db(retries: int = 60) -> None:
|
|||||||
return
|
return
|
||||||
except Exception as exc: # noqa: BLE001
|
except Exception as exc: # noqa: BLE001
|
||||||
print(f"DB not ready ({i + 1}/{retries}): {exc}")
|
print(f"DB not ready ({i + 1}/{retries}): {exc}")
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(2)
|
||||||
await engine.dispose()
|
await engine.dispose()
|
||||||
print("ERROR: database did not become ready", file=sys.stderr)
|
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)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user