diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e2049ba --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +.git +.github +.pytest_cache +.venv +__pycache__ +*.pyc +*.pyo +*.pyd +*.egg-info +.env +.env.* +!.env.example diff --git a/.env.example b/.env.example index 49a3f0a..6174d9d 100644 --- a/.env.example +++ b/.env.example @@ -3,3 +3,8 @@ APP_VERSION=0.1.0 DEBUG=false API_V1_PREFIX=/api/v1 DATABASE_URL=postgresql+psycopg://ticket_user:ticket_password@localhost:5432/ticket_api + +# Docker Compose uses the same database credentials with the internal host name "db". +POSTGRES_USER=ticket_user +POSTGRES_PASSWORD=ticket_password +POSTGRES_DB=ticket_api diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2944a6c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.12-slim + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +WORKDIR /app + +COPY pyproject.toml README.md ./ +COPY app ./app + +RUN python -m pip install --upgrade pip \ + && python -m pip install --no-cache-dir -e . + +EXPOSE 8000 + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/README.md b/README.md index 110ebc2..18a19fd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Ticket-API is a backend API for a portfolio-oriented ticketing and incident management system. It is designed for junior backend, cloud, and platform engineering roles. -This first phase provides a clean FastAPI foundation with versioned routes, a health check endpoint, basic error handling, automated testing with `pytest`, and a GitHub Actions CI workflow. +This project provides a clean FastAPI foundation with versioned routes, a health check endpoint, basic error handling, automated testing with `pytest`, SQLAlchemy models, PostgreSQL-ready configuration, Docker-based local development, and a GitHub Actions CI workflow. ## Project Goals @@ -14,14 +14,20 @@ This project is being built to demonstrate practical backend and cloud-readiness - Consistent error handling - Automated testing with `pytest` - Continuous Integration with GitHub Actions -- Preparation for future PostgreSQL persistence -- Preparation for Docker and cloud deployment +- PostgreSQL persistence readiness with SQLAlchemy +- Docker-based local development +- Preparation for future cloud deployment ## Requirements - Python 3.11+ - `pip` +For Docker-based local development: + +- Docker +- Docker Compose + ## Local Installation Create and activate a virtual environment: @@ -55,6 +61,42 @@ The API will be available at: - `http://127.0.0.1:8000/redoc` - `http://127.0.0.1:8000/api/v1/health` +## Run With Docker + +Build and start the FastAPI and PostgreSQL containers: + +```bash +docker compose up --build +``` + +The API will be available at: + +- `http://127.0.0.1:8000/docs` +- `http://127.0.0.1:8000/redoc` +- `http://127.0.0.1:8000/api/v1/health` + +The PostgreSQL container is exposed locally on port `5432`. + +Stop the containers: + +```bash +docker compose down +``` + +Stop the containers and remove the local PostgreSQL volume: + +```bash +docker compose down -v +``` + +Docker Compose passes this database URL to the API container: + +```text +postgresql+psycopg://ticket_user:ticket_password@db:5432/ticket_api +``` + +The application is not creating tables or running migrations yet. Alembic and database migrations are planned for a later phase. + ## Available Endpoint ### `GET /api/v1/health` @@ -78,26 +120,30 @@ The project includes automated tests using `pytest`. Run the tests locally: ```bash -python -m pytest +.venv\Scripts\python.exe -m pytest ``` -Current test coverage includes the health check endpoint: +Current test coverage includes: ```http GET /api/v1/health ``` -The test validates that the API: +The tests validate that the API: - Returns HTTP status code `200` - Returns `status: "ok"` - Returns `service: "ticket-api"` - Includes a `version` field +- Defines SQLAlchemy model metadata +- Uses the expected PostgreSQL psycopg database URL configuration -Test file: +Test files: ```text tests/test_health.py +tests/test_models.py +tests/test_database_config.py ``` ## Continuous Integration @@ -131,11 +177,18 @@ app/ api/ routes/ core/ + db/ + models/ schemas/ main.py tests/ test_health.py + test_models.py + test_database_config.py + +Dockerfile +docker-compose.yml .github/ workflows/ @@ -161,15 +214,13 @@ Completed: - Initial README - Automated health endpoint test with `pytest` - GitHub Actions CI workflow +- SQLAlchemy domain models +- Database configuration +- SQLAlchemy engine and session setup +- Dockerfile and Docker Compose local development setup ## Next Phase -The next phase will add persistence with PostgreSQL and initial domain models without breaking the current project structure. - -Planned models: - -- User -- Ticket -- Incident +The next phase will add database migrations without breaking the current project structure. -Future phases will include authentication, role-based access control, Docker, CI/CD improvements, and cloud deployment. +Future phases will include CRUD endpoints, authentication, role-based access control, CI/CD improvements, and cloud deployment. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8f49a12 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +services: + api: + build: + context: . + container_name: ticket-api + environment: + DATABASE_URL: postgresql+psycopg://ticket_user:ticket_password@db:5432/ticket_api + ports: + - "8000:8000" + depends_on: + db: + condition: service_healthy + + db: + image: postgres:16-alpine + container_name: ticket-api-db + environment: + POSTGRES_USER: ticket_user + POSTGRES_PASSWORD: ticket_password + POSTGRES_DB: ticket_api + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ticket_user -d ticket_api"] + interval: 5s + timeout: 5s + retries: 5 + +volumes: + postgres_data: