feat: Add Docker support and CI/CD workflows documentation; include setup instructions for Docker-based deployment
This commit is contained in:
27
README.md
27
README.md
@@ -33,3 +33,30 @@ This repository contains detailed developer and architecture documentation in th
|
|||||||
Key architecture documents: see [architecture](docs/architecture/README.md) for the arc42-based architecture documentation.
|
Key architecture documents: see [architecture](docs/architecture/README.md) for the arc42-based architecture documentation.
|
||||||
|
|
||||||
For contributors: the `routes/`, `models/` and `services/` folders contain the primary application code. Tests and E2E specs are in `tests/`.
|
For contributors: the `routes/`, `models/` and `services/` folders contain the primary application code. Tests and E2E specs are in `tests/`.
|
||||||
|
|
||||||
|
## Run with Docker
|
||||||
|
|
||||||
|
The repository ships with a multi-stage `Dockerfile` that produces a slim runtime image.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Build the image locally
|
||||||
|
docker build -t calminer:latest .
|
||||||
|
|
||||||
|
# Run the container (exposes FastAPI on http://localhost:8000)
|
||||||
|
docker run --rm -p 8000:8000 calminer:latest
|
||||||
|
|
||||||
|
# Provide environment variables (e.g., database URL)
|
||||||
|
docker run --rm -p 8000:8000 -e DATABASE_URL="postgresql://user:pass@host/db" calminer:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `docker compose` or an orchestrator of your choice to co-locate PostgreSQL/Redis alongside the app when needed. The image expects migrations to be applied before startup.
|
||||||
|
|
||||||
|
## CI/CD expectations
|
||||||
|
|
||||||
|
CalMiner uses Gitea Actions workflows stored in `.gitea/workflows/`:
|
||||||
|
|
||||||
|
- `test.yml` runs style/unit/e2e suites on every push with cached Python dependencies.
|
||||||
|
- `build-and-push.yml` builds the Docker image, reuses cached layers, and pushes to the configured registry.
|
||||||
|
- `deploy.yml` pulls the pushed image on the target host and restarts the container.
|
||||||
|
|
||||||
|
Pipelines assume the following secrets are provisioned in the Gitea instance: `GITEA_USERNAME`, `GITEA_PASSWORD`, `GITEA_REGISTRY`, `SSH_HOST`, `SSH_USERNAME`, and `SSH_PRIVATE_KEY`.
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ description: "Describe deployment topology, infrastructure components, and envir
|
|||||||
status: draft
|
status: draft
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!-- markdownlint-disable-next-line MD025 -->
|
||||||
|
|
||||||
# 07 — Deployment View
|
# 07 — Deployment View
|
||||||
|
|
||||||
## Deployment Topology
|
## Deployment Topology
|
||||||
@@ -23,8 +25,8 @@ The infrastructure components for the application include:
|
|||||||
- **Database Server**: PostgreSQL database for persisting application data.
|
- **Database Server**: PostgreSQL database for persisting application data.
|
||||||
- **Static File Server**: Serves static assets such as CSS, JavaScript, and image files.
|
- **Static File Server**: Serves static assets such as CSS, JavaScript, and image files.
|
||||||
- **Reverse Proxy (optional)**: An Nginx or Apache server can be used as a reverse proxy.
|
- **Reverse Proxy (optional)**: An Nginx or Apache server can be used as a reverse proxy.
|
||||||
- **CI/CD Pipeline (optional)**: Automated deployment pipelines can be set up using tools like GitHub Actions.
|
- **Containerization**: Docker images are generated via the repository `Dockerfile`, using a multi-stage build to keep the final runtime minimal.
|
||||||
- **Containerization (optional)**: Docker can be used to containerize the application.
|
- **CI/CD Pipeline**: Automated pipelines (Gitea Actions) run tests, build/push Docker images, and trigger deployments.
|
||||||
- **Cloud Infrastructure (optional)**: The application can be deployed on cloud platforms.
|
- **Cloud Infrastructure (optional)**: The application can be deployed on cloud platforms.
|
||||||
|
|
||||||
## Environments
|
## Environments
|
||||||
@@ -55,7 +57,32 @@ The production environment is set up for serving live traffic and includes:
|
|||||||
- Load balancer (e.g., Nginx) for distributing incoming requests
|
- Load balancer (e.g., Nginx) for distributing incoming requests
|
||||||
- Monitoring and logging tools for tracking application performance
|
- Monitoring and logging tools for tracking application performance
|
||||||
|
|
||||||
|
## Containerized Deployment Flow
|
||||||
|
|
||||||
|
The Docker-based deployment path aligns with the solution strategy documented in [04 — Solution Strategy](04_solution_strategy.md) and the CI practices captured in [14 — Testing & CI](14_testing_ci.md).
|
||||||
|
|
||||||
|
### Image Build
|
||||||
|
|
||||||
|
- The multi-stage `Dockerfile` installs dependencies in a builder layer (including system compilers and Python packages) and copies only the required runtime artifacts to the final image.
|
||||||
|
- Build arguments are minimal; environment configuration (e.g., `DATABASE_URL`) is supplied at runtime. Secrets and configuration should be passed via environment variables or an orchestrator.
|
||||||
|
- The resulting image exposes port `8000` and starts `uvicorn main:app` (s. [README.md](../README.md)).
|
||||||
|
|
||||||
|
### Runtime Environment
|
||||||
|
|
||||||
|
- For single-node deployments, run the container alongside PostgreSQL/Redis using Docker Compose or an equivalent orchestrator.
|
||||||
|
- A reverse proxy (e.g., Nginx) terminates TLS and forwards traffic to the container on port `8000`.
|
||||||
|
- Migrations must be applied prior to rolling out a new image; automation can hook into the deploy step to run `scripts/run_migrations.py`.
|
||||||
|
|
||||||
|
### CI/CD Integration
|
||||||
|
|
||||||
|
- Gitea Actions workflows reside under `.gitea/workflows/`.
|
||||||
|
- `test.yml` executes the pytest suite using cached pip dependencies.
|
||||||
|
- `build-and-push.yml` logs into the container registry, rebuilds the Docker image using GitHub Actions cache-backed layers, and pushes `latest` (and additional tags as required).
|
||||||
|
- `deploy.yml` connects to the target host via SSH, pulls the pushed tag, stops any existing container, and launches the new version.
|
||||||
|
- Required secrets: `GITEA_REGISTRY`, `GITEA_USERNAME`, `GITEA_PASSWORD`, `SSH_HOST`, `SSH_USERNAME`, `SSH_PRIVATE_KEY`.
|
||||||
|
- Extend these workflows when introducing staging/blue-green deployments; keep cross-links with [14 — Testing & CI](14_testing_ci.md) up to date.
|
||||||
|
|
||||||
## Integrations and Future Work (deployment-related)
|
## Integrations and Future Work (deployment-related)
|
||||||
|
|
||||||
- **Persistence of results**: `/api/simulations/run` currently returns in-memory results; next iteration should persist to `simulation_result` and reference scenarios.
|
- **Persistence of results**: `/api/simulations/run` currently returns in-memory results; next iteration should persist to `simulation_result` and reference scenarios.
|
||||||
- **Deployment**: documentation focuses on local development; containerization and CI/CD pipelines remain to be defined. Consider Docker + GitHub Actions or a simple Docker Compose for local stacks.
|
- **Deployment**: implement infrastructure-as-code (e.g., Terraform/Ansible) to provision the hosting environment and maintain parity across dev/stage/prod.
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ CalMiner uses a combination of unit, integration, and end-to-end tests to ensure
|
|||||||
|
|
||||||
### CI/CD
|
### CI/CD
|
||||||
|
|
||||||
- Use GitHub Actions for CI.
|
- Use Gitea Actions for CI/CD; workflows live under `.gitea/workflows/`.
|
||||||
- Run tests on pull requests.
|
- `test.yml` runs on every push with cached Python dependencies via `actions/cache@v3`.
|
||||||
- Code coverage target: 80% (using pytest-cov).
|
- `build-and-push.yml` builds the Docker image with `docker/build-push-action@v2`, reusing GitHub Actions cache-backed layers, and pushes to the Gitea registry.
|
||||||
|
- `deploy.yml` connects to the target host (via `appleboy/ssh-action`) to pull the freshly pushed image and restart the container.
|
||||||
|
- Mandatory secrets: `GITEA_USERNAME`, `GITEA_PASSWORD`, `GITEA_REGISTRY`, `SSH_HOST`, `SSH_USERNAME`, `SSH_PRIVATE_KEY`.
|
||||||
|
- Run tests on pull requests to shared branches; enforce coverage target ≥80% (pytest-cov).
|
||||||
|
|
||||||
### Running Tests
|
### Running Tests
|
||||||
|
|
||||||
@@ -34,7 +37,7 @@ CalMiner uses a combination of unit, integration, and end-to-end tests to ensure
|
|||||||
|
|
||||||
Organize tests under the `tests/` directory mirroring the application structure:
|
Organize tests under the `tests/` directory mirroring the application structure:
|
||||||
|
|
||||||
```text
|
````text
|
||||||
tests/
|
tests/
|
||||||
unit/
|
unit/
|
||||||
test_<module>.py
|
test_<module>.py
|
||||||
@@ -71,7 +74,7 @@ To run the Playwright tests:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
pytest tests/e2e/
|
pytest tests/e2e/
|
||||||
```
|
````
|
||||||
|
|
||||||
To run headed mode:
|
To run headed mode:
|
||||||
|
|
||||||
@@ -93,9 +96,22 @@ pytest tests/e2e/ --headed
|
|||||||
|
|
||||||
### CI Integration
|
### CI Integration
|
||||||
|
|
||||||
- Configure GitHub Actions workflow in `.github/workflows/ci.yml` to:
|
`test.yml` encapsulates the steps below:
|
||||||
- Install dependencies, including Playwright browsers (`playwright install`).
|
|
||||||
- Run `pytest` with coverage for unit tests.
|
- Check out the repository and set up Python 3.10.
|
||||||
- Run `pytest tests/e2e/` for E2E tests.
|
- Restore the pip cache (keyed by `requirements.txt`).
|
||||||
- Fail on coverage <80%.
|
- Install project dependencies and Playwright browsers (if needed for E2E).
|
||||||
- Upload coverage artifacts under `reports/coverage/`.
|
- Run `pytest` (extend with `--cov` flags when enforcing coverage).
|
||||||
|
|
||||||
|
`build-and-push.yml` adds:
|
||||||
|
|
||||||
|
- Registry login using repository secrets.
|
||||||
|
- Docker image build/push with GHA cache storage (`cache-from/cache-to` set to `type=gha`).
|
||||||
|
|
||||||
|
`deploy.yml` handles:
|
||||||
|
|
||||||
|
- SSH into the deployment host.
|
||||||
|
- Pull the tagged image from the registry.
|
||||||
|
- Stop, remove, and relaunch the `calminer` container exposing port 8000.
|
||||||
|
|
||||||
|
When adding new workflows, mirror this structure to ensure secrets, caching, and deployment steps remain aligned with the production environment.
|
||||||
|
|||||||
@@ -22,6 +22,23 @@ pip install -r requirements.txt
|
|||||||
uvicorn main:app --reload
|
uvicorn main:app --reload
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Docker-based setup
|
||||||
|
|
||||||
|
To build and run the application using Docker instead of a local Python environment:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Build the application image (multi-stage build keeps runtime small)
|
||||||
|
docker build -t calminer:latest .
|
||||||
|
|
||||||
|
# Start the container on port 8000
|
||||||
|
docker run --rm -p 8000:8000 calminer:latest
|
||||||
|
|
||||||
|
# Supply environment variables (e.g., Postgres connection)
|
||||||
|
docker run --rm -p 8000:8000 -e DATABASE_URL="postgresql://user:pass@host/db" calminer:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
If you maintain a Postgres or Redis dependency locally, consider authoring a `docker compose` stack that pairs them with the app container. The Docker image expects the database to be reachable and migrations executed before serving traffic.
|
||||||
|
|
||||||
## Usage Overview
|
## Usage Overview
|
||||||
|
|
||||||
- **API base URL**: `http://localhost:8000/api`
|
- **API base URL**: `http://localhost:8000/api`
|
||||||
|
|||||||
Reference in New Issue
Block a user