Fix port binding issue by adding dynamic port selection

This commit is contained in:
Automated Action 2025-05-16 10:35:35 +00:00
parent 8d79a1b61d
commit e02176bc94
2 changed files with 62 additions and 1 deletions

View File

@ -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
View File

@ -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)