Fix deploy port conflict: auto-detect free port + persist to .env
- Read API/WEB/PG/REDIS ports from .env on startup (Docker Compose loads .env directly, shell exports are ignored by it) - check_port: auto-find next free port instead of interactive prompt - set_env_port: write chosen port back to .env so it persists across runs - port_taken_by_other: use 'ss | grep' instead of ss sport filter (more reliable) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2b31281be5
commit
5c052e718d
1 changed files with 47 additions and 31 deletions
78
deploy.sh
78
deploy.sh
|
|
@ -18,11 +18,12 @@ fi
|
|||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# ── Default ports ─────────────────────────────────────────────────────────────
|
||||
API_PORT=${API_PORT:-8000}
|
||||
WEB_PORT=${WEB_PORT:-3000}
|
||||
PG_PORT=${PG_PORT:-5432}
|
||||
REDIS_PORT=${REDIS_PORT:-6379}
|
||||
# ── Default ports — read from .env first, then env, then hardcoded default ────
|
||||
env_val() { local key=$1 def=$2; grep -E "^${key}=" .env 2>/dev/null | cut -d= -f2 | tr -d '"' | head -1 | grep -v '^$' || echo "$def"; }
|
||||
API_PORT=${API_PORT:-$(env_val API_PORT 8000)}
|
||||
WEB_PORT=${WEB_PORT:-$(env_val WEB_PORT 3000)}
|
||||
PG_PORT=${PG_PORT:-$(env_val PG_PORT 5432)}
|
||||
REDIS_PORT=${REDIS_PORT:-$(env_val REDIS_PORT 6379)}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# STEP 1: Prerequisites — install missing packages
|
||||
|
|
@ -68,11 +69,41 @@ sudo a2enmod proxy proxy_http proxy_wstunnel headers rewrite -q
|
|||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
info "Step 1.5: Checking port availability..."
|
||||
|
||||
# Returns the PID+process using a port, empty if free or used by our containers
|
||||
port_owner() {
|
||||
# Check if a port is in use by a NON-deckforge process
|
||||
port_taken_by_other() {
|
||||
local port=$1
|
||||
# ss -tlnp output: "users:(("process",pid=NNN,...))"
|
||||
ss -tlnp "sport = :${port}" 2>/dev/null | awk 'NR>1 {print $NF}' | grep -oP '"[^"]+",pid=\K[0-9]+' | head -1
|
||||
# Check if anything is listening on this port
|
||||
ss -tlnp 2>/dev/null | grep -qw ":${port}" || return 1
|
||||
|
||||
# Check if it belongs to OUR docker-compose project
|
||||
local our_ids
|
||||
our_ids=$(docker compose -f docker-compose.yml -f docker-compose.prod.yml ps -q 2>/dev/null || true)
|
||||
if [[ -n "$our_ids" ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
if docker inspect $our_ids 2>/dev/null | grep -q "\"HostPort\": \"${port}\""; then
|
||||
return 1 # It's ours — will be replaced on restart
|
||||
fi
|
||||
fi
|
||||
return 0 # Taken by someone else
|
||||
}
|
||||
|
||||
# Find next free port starting from given port
|
||||
find_free_port() {
|
||||
local port=$1
|
||||
while port_taken_by_other "$port"; do
|
||||
port=$((port + 1))
|
||||
done
|
||||
echo "$port"
|
||||
}
|
||||
|
||||
# Write or update a key in .env
|
||||
set_env_port() {
|
||||
local key=$1 val=$2
|
||||
if grep -qE "^${key}=" .env 2>/dev/null; then
|
||||
sed -i "s|^${key}=.*|${key}=${val}|" .env
|
||||
else
|
||||
echo "${key}=${val}" >> .env
|
||||
fi
|
||||
}
|
||||
|
||||
check_port() {
|
||||
|
|
@ -80,32 +111,17 @@ check_port() {
|
|||
local varname=$2
|
||||
local service=$3
|
||||
|
||||
local pid
|
||||
pid=$(port_owner "$port" || true)
|
||||
|
||||
if [[ -z "$pid" ]]; then
|
||||
info " Port $port ($service): free"
|
||||
if ! port_taken_by_other "$port"; then
|
||||
info " Port $port ($service): OK"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if it belongs to OUR docker-compose project (not other apps on server)
|
||||
local our_ids
|
||||
our_ids=$(docker compose -f docker-compose.yml -f docker-compose.prod.yml ps -q 2>/dev/null || true)
|
||||
|
||||
if [[ -n "$our_ids" ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
if docker inspect $our_ids 2>/dev/null \
|
||||
| grep -q "\"HostPort\": \"${port}\""; then
|
||||
info " Port $port ($service): used by our container (will be replaced on restart)"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
warn " Port $port ($service) is in use by PID $pid ($proc_name)"
|
||||
read -rp " Enter alternative port for $service [$port]: " new_port
|
||||
new_port="${new_port:-$port}"
|
||||
local new_port
|
||||
new_port=$(find_free_port "$((port + 1))")
|
||||
warn " Port $port ($service) is taken by another process — using $new_port instead"
|
||||
eval "$varname=$new_port"
|
||||
info " Using port $new_port for $service"
|
||||
set_env_port "$varname" "$new_port"
|
||||
info " Saved ${varname}=${new_port} to .env"
|
||||
}
|
||||
|
||||
check_port "$API_PORT" API_PORT "api"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue