Fix port binding issue by adding dynamic port selection
This commit is contained in:
parent
8d79a1b61d
commit
e02176bc94
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
@ -10,9 +11,14 @@ class Settings(BaseSettings):
|
|||||||
extra="ignore"
|
extra="ignore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# API settings
|
||||||
API_V1_STR: str = "/api/v1"
|
API_V1_STR: str = "/api/v1"
|
||||||
PROJECT_NAME: str = "Todo Application"
|
PROJECT_NAME: str = "Todo Application"
|
||||||
|
|
||||||
|
# Server settings
|
||||||
|
HOST: str = "0.0.0.0" # Listen on all available interfaces
|
||||||
|
PORT: int = 8000 # Default port
|
||||||
|
|
||||||
# Database settings
|
# Database settings
|
||||||
DB_DIR: Path = Path("/app") / "storage" / "db"
|
DB_DIR: Path = Path("/app") / "storage" / "db"
|
||||||
SQLALCHEMY_DATABASE_URL: str = f"sqlite:///{DB_DIR}/db.sqlite"
|
SQLALCHEMY_DATABASE_URL: str = f"sqlite:///{DB_DIR}/db.sqlite"
|
||||||
@ -21,5 +27,13 @@ class Settings(BaseSettings):
|
|||||||
super().__init__(**data)
|
super().__init__(**data)
|
||||||
self.DB_DIR.mkdir(parents=True, exist_ok=True)
|
self.DB_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Override settings from environment variables if they exist
|
||||||
|
if "PORT" in os.environ:
|
||||||
|
try:
|
||||||
|
self.PORT = int(os.environ["PORT"])
|
||||||
|
except ValueError:
|
||||||
|
# If PORT env var isn't a valid int, keep the default
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
49
main.py
49
main.py
@ -1,9 +1,17 @@
|
|||||||
|
import logging
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
from app.api.api import api_router
|
from app.api.api import api_router
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title=settings.PROJECT_NAME,
|
title=settings.PROJECT_NAME,
|
||||||
openapi_url=f"{settings.API_V1_STR}/openapi.json",
|
openapi_url=f"{settings.API_V1_STR}/openapi.json",
|
||||||
@ -13,5 +21,44 @@ app = FastAPI(
|
|||||||
|
|
||||||
app.include_router(api_router, prefix=settings.API_V1_STR)
|
app.include_router(api_router, prefix=settings.API_V1_STR)
|
||||||
|
|
||||||
|
def find_available_port(start_port, max_attempts=10):
|
||||||
|
"""Try to find an available port starting from start_port"""
|
||||||
|
for port in range(start_port, start_port + max_attempts):
|
||||||
|
try:
|
||||||
|
# Try to create a socket with the port
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.bind((settings.HOST, port))
|
||||||
|
# If we get here, the port is available
|
||||||
|
return port
|
||||||
|
except OSError:
|
||||||
|
# Port is already in use, try the next one
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If we get here, no ports were available in our range
|
||||||
|
port_range_end = start_port + max_attempts - 1
|
||||||
|
logger.warning(
|
||||||
|
f"Could not find an available port in range {start_port}-{port_range_end}"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
port = settings.PORT
|
||||||
|
|
||||||
|
# Check if the port is already in use
|
||||||
|
try:
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.bind((settings.HOST, port))
|
||||||
|
except OSError:
|
||||||
|
logger.warning(
|
||||||
|
f"Port {port} is already in use. Trying to find an available port..."
|
||||||
|
)
|
||||||
|
port = find_available_port(port + 1)
|
||||||
|
|
||||||
|
if port is None:
|
||||||
|
logger.error("Could not find an available port. Exiting.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
logger.info(f"Using alternative port: {port}")
|
||||||
|
|
||||||
|
# Start the server with the available port
|
||||||
|
uvicorn.run("main:app", host=settings.HOST, port=port, reload=True)
|
Loading…
x
Reference in New Issue
Block a user