From 229e1ca40cc155411a192865fc19b2e6b89eaa81 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:07:59 -0400 Subject: [PATCH 01/26] Create basic Dockerfile --- Dockerfile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..92de104 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.12-slim + +# Git is needed to install the git-based dependency in requirements.txt +RUN apt-get update + && apt-get install -y git + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY app/ ./app/ + +EXPOSE 8000 + +# Run FastAPI via Uvicorn +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file From d5b85823643a41b2d30072689442570684cca854 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:01:08 -0400 Subject: [PATCH 02/26] Add DB root password to .env and move to project root --- app/dependencies.py | 7 ++++--- app/example.env => example.env | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) rename app/example.env => example.env (63%) diff --git a/app/dependencies.py b/app/dependencies.py index 2879e86..b9c3def 100644 --- a/app/dependencies.py +++ b/app/dependencies.py @@ -2,12 +2,12 @@ from contextlib import asynccontextmanager from typing import Annotated, AsyncGenerator, Generator +import carpi_data_model.models as models from fastapi import Depends, FastAPI from pydantic_settings import BaseSettings, SettingsConfigDict -from sqlalchemy.engine import Engine from sqlalchemy import create_engine +from sqlalchemy.engine import Engine from sqlalchemy.orm import Session, sessionmaker -import carpi_data_model.models as models class _Settings(BaseSettings): @@ -18,7 +18,8 @@ class _Settings(BaseSettings): db_password: str db_schema: str model_config = SettingsConfigDict( - env_file=os.path.join(os.path.dirname(__file__), ".env") + env_file=os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env"), + extra="ignore", ) diff --git a/app/example.env b/example.env similarity index 63% rename from app/example.env rename to example.env index bbdb23a..519508a 100644 --- a/app/example.env +++ b/example.env @@ -1,5 +1,9 @@ # Create a file named ".env" in this directory with the following variables +# This root password is only used for instantiating the MySQL container in +# Docker Compose. +DB_ROOT_PASSWORD="password" + DB_DIALECT="mysql" DB_API="mysqlconnector" DB_HOSTNAME="hostname:port" From dec915dcf5e4d6bf1d43194f9d8a958b8428cbfb Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:02:13 -0400 Subject: [PATCH 03/26] Add Docker and Docker Compose files --- Dockerfile | 6 +++--- docker-compose.yml | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile index 92de104..cef872c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ FROM python:3.12-slim # Git is needed to install the git-based dependency in requirements.txt -RUN apt-get update - && apt-get install -y git - && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + +WORKDIR /api COPY requirements.txt . diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..607fedf --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +services: + db: + image: mysql:8.0 + restart: always + environment: + MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + MYSQL_DATABASE: ${DB_SCHEMA} + MYSQL_USER: ${DB_USERNAME} + MYSQL_PASSWORD: ${DB_PASSWORD} + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 5s + timeout: 5s + retries: 10 + + api: + build: . + restart: always + ports: + - "8000:8000" + environment: + DB_DIALECT: ${DB_DIALECT} + DB_API: ${DB_API} + DB_HOSTNAME: ${DB_HOSTNAME} + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + DB_SCHEMA: ${DB_SCHEMA} + depends_on: + db: + condition: service_healthy + +volumes: + mysql_data: From 0e540fd2c12d3296d0603f76fe604a4451657129 Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Tue, 21 Apr 2026 23:57:05 -0400 Subject: [PATCH 04/26] Remove redundant variable names in Docker Compose --- docker-compose.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 607fedf..f219ef0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,13 +22,8 @@ services: restart: always ports: - "8000:8000" - environment: - DB_DIALECT: ${DB_DIALECT} - DB_API: ${DB_API} - DB_HOSTNAME: ${DB_HOSTNAME} - DB_USERNAME: ${DB_USERNAME} - DB_PASSWORD: ${DB_PASSWORD} - DB_SCHEMA: ${DB_SCHEMA} + env_file: + - .env depends_on: db: condition: service_healthy From 8e8d82758046adad4ba78b776990113e35c4b971 Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:16:08 -0400 Subject: [PATCH 05/26] Restore .env variable interpolation --- docker-compose.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f219ef0..1da03a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,8 +22,13 @@ services: restart: always ports: - "8000:8000" - env_file: - - .env + environment: + DB_DIALECT: mysql + DB_API: ${DB_API} + DB_HOSTNAME: db:3306 + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + DB_SCHEMA: ${DB_SCHEMA} depends_on: db: condition: service_healthy From 9531ebe256875417bf0945485164e7cd244c88a8 Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:44:05 -0400 Subject: [PATCH 06/26] Fix DB health check passing prematurely --- docker-compose.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1da03a4..31e9bce 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,7 +12,17 @@ services: volumes: - mysql_data:/var/lib/mysql healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + test: + [ + "CMD", + "mysqladmin", + "ping", + "-h", + "localhost", + "-u", + "${DB_USERNAME}", + "--password=${DB_PASSWORD}", + ] interval: 5s timeout: 5s retries: 10 From b658cfe47b811842ea3c30c94a8e561bfc604bff Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:50:50 -0400 Subject: [PATCH 07/26] Second fix to DB health check --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 31e9bce..e11e017 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,7 @@ services: "mysqladmin", "ping", "-h", - "localhost", + "127.0.0.1", "-u", "${DB_USERNAME}", "--password=${DB_PASSWORD}", From 201957a03cf7c3bdec0c49c29a0a3e718a62c4ae Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Wed, 22 Apr 2026 00:57:22 -0400 Subject: [PATCH 08/26] Remove hardcoded variable values in Docker Compose --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index e11e017..94e8438 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,9 +33,9 @@ services: ports: - "8000:8000" environment: - DB_DIALECT: mysql + DB_DIALECT: ${DB_DIALECT} DB_API: ${DB_API} - DB_HOSTNAME: db:3306 + DB_HOSTNAME: ${DB_HOSTNAME} DB_USERNAME: ${DB_USERNAME} DB_PASSWORD: ${DB_PASSWORD} DB_SCHEMA: ${DB_SCHEMA} From c47f74e21eb138a43de00b9e8914ca30f9e69fa9 Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Wed, 22 Apr 2026 23:26:48 -0400 Subject: [PATCH 09/26] Modify Black check to call shared workflow --- .github/workflows/black-check.yml | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/.github/workflows/black-check.yml b/.github/workflows/black-check.yml index 1d11de9..107b541 100644 --- a/.github/workflows/black-check.yml +++ b/.github/workflows/black-check.yml @@ -1,25 +1,11 @@ -name: Black Check +name: Black Formatting Check +# Run on every push and pull request on: [push, pull_request] jobs: - format-check: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.12.2' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install black - - - name: Run Black check - run: black --check . - \ No newline at end of file + call-format-check: + uses: project-carpi/.github/.github/workflows/black-check.yml@main + permissions: + contents: read + secrets: inherit From 3831cba774a2d086ef20c417dbe4ed48c87b3d5b Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Thu, 23 Apr 2026 02:29:50 -0400 Subject: [PATCH 10/26] Enhance Dockerfile readability --- Dockerfile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index cef872c..79c20a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,19 @@ FROM python:3.12-slim # Git is needed to install the git-based dependency in requirements.txt -RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y git +# Clean up apt cache to reduce image size +RUN rm -rf /var/lib/apt/lists/* + +# Store all application files in /api WORKDIR /api +# Copy the requirements file and install dependencies COPY requirements.txt . - RUN pip install --no-cache-dir -r requirements.txt -COPY app/ ./app/ +COPY . . EXPOSE 8000 From 5d59083f4f1affc30c123e2e060705a1be793e59 Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Thu, 23 Apr 2026 02:29:55 -0400 Subject: [PATCH 11/26] Create .dockerignore --- .dockerignore | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..628b32e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +# Ignore all files + +* + +# Whitelist necessary build files +!requirements.txt + +# Allow Docker to read app directory +!app/ + +# Ignore everything inside app +app/* + +# Only allow .py files within app and its subdirectories +!app/**/*.py From fc5b97c0e2ed46ec412b4edfdc9c68c93b65e8ae Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Thu, 23 Apr 2026 02:30:32 -0400 Subject: [PATCH 12/26] Include shared dev Compose and refactor API service --- docker-compose.yml | 78 ++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 94e8438..d1c02b9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,47 +1,49 @@ -services: - db: - image: mysql:8.0 - restart: always - environment: - MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} - MYSQL_DATABASE: ${DB_SCHEMA} - MYSQL_USER: ${DB_USERNAME} - MYSQL_PASSWORD: ${DB_PASSWORD} - ports: - - "3306:3306" - volumes: - - mysql_data:/var/lib/mysql - healthcheck: - test: - [ - "CMD", - "mysqladmin", - "ping", - "-h", - "127.0.0.1", - "-u", - "${DB_USERNAME}", - "--password=${DB_PASSWORD}", - ] - interval: 5s - timeout: 5s - retries: 10 +# Docker Compose configuration for the CARPI API environment. +# +# This Compose file includes a shared development environment configuration +# from the Project-CARPI/.github repository, which contains a database service +# and a shared Docker network for testing. +# +# To start the development environment, run: +# docker compose run --rm api && docker compose down +# +# This will start both the shared development environment and the carpi-api +# container. After the API container is stopped, the "docker compose down" will +# stop the shared development environment. +# +# The test database volume persists between Docker start and stop cycles so +# that test data remains available across both development sessions and other +# services that depend on the database. The volume must be manually removed in +# order to build the database from scratch. + +name: carpi-api-dev-environment +include: + - https://github.com/Project-CARPI/.github.git#main:shared-dev-env/docker-compose.yml + +services: api: build: . - restart: always + image: carpi-api:latest + container_name: carpi-api + # Ensure image is built locally and is not pulled from a registry + pull_policy: build + restart: on-failure ports: - "8000:8000" + env_file: + - .env + # Override the DB_HOSTNAME environment variable environment: - DB_DIALECT: ${DB_DIALECT} - DB_API: ${DB_API} - DB_HOSTNAME: ${DB_HOSTNAME} - DB_USERNAME: ${DB_USERNAME} - DB_PASSWORD: ${DB_PASSWORD} - DB_SCHEMA: ${DB_SCHEMA} + DB_HOSTNAME: db:3306 + # Mount local code over the code built into the container for automatic + # reloading during development. + volumes: + - .:/api depends_on: db: condition: service_healthy - -volumes: - mysql_data: + develop: + watch: + - action: rebuild + path: requirements.txt From 1144b0e4ad234dd04455627f270446a46c96b9db Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Thu, 23 Apr 2026 02:32:47 -0400 Subject: [PATCH 13/26] Add clarifying comment to Dockerfile --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 79c20a0..3d4fff6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,8 +13,10 @@ WORKDIR /api COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt +# Copy the rest of the application code into the container COPY . . +# Indicate that the container should listen on port 8000 EXPOSE 8000 # Run FastAPI via Uvicorn From bb557051558d8002433734474585465f78c0ba8c Mon Sep 17 00:00:00 2001 From: Raymond <42894676+ramonechen@users.noreply.github.com> Date: Thu, 23 Apr 2026 02:32:53 -0400 Subject: [PATCH 14/26] Create image-publish.yml --- .github/workflows/image-publish.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/image-publish.yml diff --git a/.github/workflows/image-publish.yml b/.github/workflows/image-publish.yml new file mode 100644 index 0000000..3136378 --- /dev/null +++ b/.github/workflows/image-publish.yml @@ -0,0 +1,15 @@ +name: Build and Push Docker Image to GHCR + +# Run this workflow every time code is pushed or merged to the main branch +on: + push: + branches: + - main + +jobs: + call-build-and-push: + uses: project-carpi/.github/.github/workflows/image-publish.yml@main + permissions: + contents: read + packages: write + secrets: inherit From f532cd8df39ebb1fd7a3f5f44e6b3b196d8321e1 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:00:46 -0400 Subject: [PATCH 15/26] Make environment variables explicit --- docker-compose.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d1c02b9..751a508 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,11 +31,15 @@ services: restart: on-failure ports: - "8000:8000" - env_file: - - .env - # Override the DB_HOSTNAME environment variable environment: + DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + DB_DIALECT: ${DB_DIALECT} + DB_API: ${DB_API} + # Hardcode the DB_HOSTNAME environment variable DB_HOSTNAME: db:3306 + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + DB_SCHEMA: ${DB_SCHEMA} # Mount local code over the code built into the container for automatic # reloading during development. volumes: From 702ee3596f35f0cef949bc5cf240bd4f93119f65 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 18:52:54 -0400 Subject: [PATCH 16/26] Add comment in Compose to clarify possible warning --- docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 751a508..05f9ad1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,9 @@ # container. After the API container is stopped, the "docker compose down" will # stop the shared development environment. # +# A warning may appear about the test database volume already existing. This is +# expected and can be safely ignored. +# # The test database volume persists between Docker start and stop cycles so # that test data remains available across both development sessions and other # services that depend on the database. The volume must be manually removed in From 5a83d14dec2ea923f6436bd051c327e753b2dd85 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:40:26 -0400 Subject: [PATCH 17/26] Remove mention of shared Docker network in Compose --- docker-compose.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 05f9ad1..7732e14 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,7 @@ # Docker Compose configuration for the CARPI API environment. # # This Compose file includes a shared development environment configuration -# from the Project-CARPI/.github repository, which contains a database service -# and a shared Docker network for testing. +# from the Project-CARPI/.github repository, which contains a database service. # # To start the development environment, run: # docker compose run --rm api && docker compose down From 2557b9b471097b27dfa9d8f9002aefcf1cc17319 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:40:37 -0400 Subject: [PATCH 18/26] Clarify example.env --- example.env | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/example.env b/example.env index 519508a..413468f 100644 --- a/example.env +++ b/example.env @@ -1,4 +1,9 @@ -# Create a file named ".env" in this directory with the following variables +# Create a file named ".env" in this directory with the following variables. +# If using Docker Compose for development, these values can be used as-is. + +# This only needs to be set if the database is different from the one used +# in the Docker Compose environment. +DB_HOSTNAME="hostname:port" # This root password is only used for instantiating the MySQL container in # Docker Compose. @@ -6,7 +11,6 @@ DB_ROOT_PASSWORD="password" DB_DIALECT="mysql" DB_API="mysqlconnector" -DB_HOSTNAME="hostname:port" DB_USERNAME="username" DB_PASSWORD="password" DB_SCHEMA="schema" \ No newline at end of file From 7ab08926b539d01a6f6a878a1921c939f6525aa1 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:40:43 -0400 Subject: [PATCH 19/26] Fill in README --- README.md | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e6d849..42246a5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,32 @@ -# CARPI-Backend-FastAPI +# CARPI Course Planner - API -FastAPI re-write of the old Spring Boot API. +This is the API service for the CARPI Course Planner application. It is designed to work in tandem with the [frontend](https://github.com/Project-CARPI/site) and [SIS scraper](https://github.com/Project-CARPI/sis-scraper). + +## Running the API + +### Prerequisites + +- **[Docker](https://www.docker.com/products/docker-desktop/)** (Required): Used for the streamlined development environment setup. +- **[Python >= 3.12](https://www.python.org/)** (Optional): Useful for code editor linting or running the API locally without Docker. + +### Setup Instructions + +**1. Configure Environment Variables** + +Create a copy of the `example.env` file in the project root and rename it to `.env`. + +The default values provided in the example file will work out of the box, but they can be customized as needed. + +**2. Start the Development Environment** + +With Docker Engine running, execute the following command in your terminal: + +```bash +docker compose run --rm api && docker compose down +``` + +### About the Database Environment + +- **Shared Database:** The development environment pulls a shared MySQL database service definition from an external repository, creating a local database volume. +- **Data Persistence:** The test database volume persists between Docker start and stop cycles, ensuring test data remains available across development sessions and for other services that depend on the database. +- **Resetting the Database:** To completely rebuild the database from scratch, you must manually remove the corresponding Docker volume prior to starting the environment. From a2a62bf27f10d5366a9aaeb50a7d39de9377ec7e Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:48:17 -0400 Subject: [PATCH 20/26] Add --service-ports to Compose command --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7732e14..1d66fd3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ # from the Project-CARPI/.github repository, which contains a database service. # # To start the development environment, run: -# docker compose run --rm api && docker compose down +# docker compose run --rm --service-ports api && docker compose down # # This will start both the shared development environment and the carpi-api # container. After the API container is stopped, the "docker compose down" will From 1137df4f1b50320f5d1ba7488506c85211177126 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:51:22 -0400 Subject: [PATCH 21/26] Update README setup command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42246a5..f423c6b 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The default values provided in the example file will work out of the box, but th With Docker Engine running, execute the following command in your terminal: ```bash -docker compose run --rm api && docker compose down +docker compose run --rm --service-ports api && docker compose down ``` ### About the Database Environment From 420a5ba84ba9b0123f254601b79d4b61519aee58 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:51:37 -0400 Subject: [PATCH 22/26] Add helpful runtime tips to README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index f423c6b..94543d9 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,11 @@ With Docker Engine running, execute the following command in your terminal: docker compose run --rm --service-ports api && docker compose down ``` +While the container is running: + +- **Live Reloading:** Local files are mounted to the running container, so the API service will automatically respond to live changes in your source code. +- **API Documentation:** A list of endpoint definitions and interactive Swagger documentation can be found at http://localhost:8000/docs. + ### About the Database Environment - **Shared Database:** The development environment pulls a shared MySQL database service definition from an external repository, creating a local database volume. From f540bf0ca29d8a1545459fe0dc723720d479fc6d Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:07:56 -0400 Subject: [PATCH 23/26] Remove DB_ROOT_PASSWORD from Compose --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1d66fd3..ea79c7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,6 @@ services: ports: - "8000:8000" environment: - DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} DB_DIALECT: ${DB_DIALECT} DB_API: ${DB_API} # Hardcode the DB_HOSTNAME environment variable From ee772e72e330d1b5c685992905ee3401d7a87006 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:09:36 -0400 Subject: [PATCH 24/26] Reduce layering in Dockerfile --- Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3d4fff6..391b241 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,9 @@ FROM python:3.12-slim # Git is needed to install the git-based dependency in requirements.txt -RUN apt-get update && apt-get install -y git - -# Clean up apt cache to reduce image size -RUN rm -rf /var/lib/apt/lists/* +RUN apt-get update && \ + apt-get install -y git && \ + rm -rf /var/lib/apt/lists/* # Store all application files in /api WORKDIR /api From f7f6ec6a74299893aef7ffd48356986c21190f32 Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:16:30 -0400 Subject: [PATCH 25/26] Add dev and prod stages to Dockerfile This is to allow live reloading to work correctly in development, while maintaining integrity of the production build. --- Dockerfile | 13 +++++++++++-- docker-compose.yml | 4 +++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 391b241..61b0fae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.12-slim +FROM python:3.12-slim AS base # Git is needed to install the git-based dependency in requirements.txt RUN apt-get update && \ @@ -18,5 +18,14 @@ COPY . . # Indicate that the container should listen on port 8000 EXPOSE 8000 -# Run FastAPI via Uvicorn +# --- DEVELOPMENT STAGE --- +FROM base as dev + +# Run Uvicorn with reload enabled for development +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] + +### --- PRODUCTION STAGE --- +FROM base as prod + +# Run Uvicorn for production CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index ea79c7d..a7bbb2e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,7 +25,9 @@ include: services: api: - build: . + build: + context: . + target: dev image: carpi-api:latest container_name: carpi-api # Ensure image is built locally and is not pulled from a registry From 3ed1060b05daffa5aae9f3c37bc84bdf07ac885f Mon Sep 17 00:00:00 2001 From: Raymond Chen <42894676+ramonechen@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:17:27 -0400 Subject: [PATCH 26/26] Remove Compose watch directive With the docker run command, the watch directive is ignored. And I don't think it will be very often that the development environment will be kept running as a developer adds/removes dependencies from requirements.txt. --- docker-compose.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a7bbb2e..c9cc47d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,7 +50,3 @@ services: depends_on: db: condition: service_healthy - develop: - watch: - - action: rebuild - path: requirements.txt