Containerize backend with Docker Compose
Added Docker support for easy deployment: - Dockerfile: Python 3.11 slim image with FastAPI app - docker-compose.yml: Service definition with volume mounting for data persistence - .dockerignore: Exclude unnecessary files from Docker build - database.py: Updated to store SQLite DB in ./data directory for volume persistence - .gitignore: Added entries for database files and data directory - README.md: Comprehensive documentation with Docker and local setup instructions The application can now be run with: docker compose up -d Database persists in ./data directory mounted as a volume
This commit is contained in:
19
.dockerignore
Normal file
19
.dockerignore
Normal file
@@ -0,0 +1,19 @@
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
*.so
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
.git
|
||||
.gitignore
|
||||
*.db
|
||||
*.db-journal
|
||||
.env
|
||||
.venv
|
||||
venv/
|
||||
ENV/
|
||||
data/
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -205,3 +205,9 @@ cython_debug/
|
||||
marimo/_static/
|
||||
marimo/_lsp/
|
||||
__marimo__/
|
||||
|
||||
# Seismo Fleet Manager
|
||||
# SQLite database files
|
||||
*.db
|
||||
*.db-journal
|
||||
data/
|
||||
|
||||
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy requirements first for better caching
|
||||
COPY requirements.txt .
|
||||
|
||||
# Install dependencies
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8000
|
||||
|
||||
# Run the application
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
251
README.md
251
README.md
@@ -1,2 +1,249 @@
|
||||
# seismo-fleet-manager
|
||||
Web app and backend for tracking deployed units.
|
||||
# Seismo Fleet Manager - Backend v0.1
|
||||
|
||||
Backend API for managing seismograph fleet status. Track multiple seismographs calling in data from remote deployments, monitor their status, and manage your fleet through a unified database.
|
||||
|
||||
## Features
|
||||
|
||||
- **Fleet Monitoring**: Track all seismograph units in one place
|
||||
- **Status Management**: Automatically mark units as OK, Pending (>12h), or Missing (>24h)
|
||||
- **Data Ingestion**: Accept reports from emitter scripts via REST API
|
||||
- **SQLite Storage**: Lightweight, file-based database for easy deployment
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **FastAPI**: Modern, fast web framework
|
||||
- **SQLAlchemy**: SQL toolkit and ORM
|
||||
- **SQLite**: Lightweight database
|
||||
- **uvicorn**: ASGI server
|
||||
- **Docker**: Containerization for easy deployment
|
||||
|
||||
## Quick Start with Docker Compose (Recommended)
|
||||
|
||||
### Prerequisites
|
||||
- Docker and Docker Compose installed
|
||||
|
||||
### Running the Application
|
||||
|
||||
1. **Start the service:**
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
2. **Check logs:**
|
||||
```bash
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
3. **Stop the service:**
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
The API will be available at `http://localhost:8000`
|
||||
|
||||
### Data Persistence
|
||||
|
||||
The SQLite database is stored in the `./data` directory, which is mounted as a volume. Your data will persist even if you restart or rebuild the container.
|
||||
|
||||
## Local Development (Without Docker)
|
||||
|
||||
### Prerequisites
|
||||
- Python 3.11+
|
||||
- pip
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Install dependencies:**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. **Run the server:**
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
Or with auto-reload:
|
||||
```bash
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
|
||||
The API will be available at `http://localhost:8000`
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Root
|
||||
- **GET** `/` - Health check
|
||||
|
||||
### Emitter Report
|
||||
- **POST** `/emitters/report`
|
||||
- Submit status report from a seismograph unit
|
||||
- **Request Body:**
|
||||
```json
|
||||
{
|
||||
"unit": "SEISMO-001",
|
||||
"unit_type": "series3",
|
||||
"timestamp": "2025-11-20T10:30:00",
|
||||
"file": "event_20251120_103000.dat",
|
||||
"status": "OK"
|
||||
}
|
||||
```
|
||||
- **Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Emitter report received",
|
||||
"unit": "SEISMO-001",
|
||||
"status": "OK"
|
||||
}
|
||||
```
|
||||
|
||||
### Fleet Status
|
||||
- **GET** `/fleet/status`
|
||||
- Retrieve status of all seismograph units
|
||||
- **Response:**
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "SEISMO-001",
|
||||
"unit_type": "series3",
|
||||
"last_seen": "2025-11-20T10:30:00",
|
||||
"last_file": "event_20251120_103000.dat",
|
||||
"status": "OK",
|
||||
"notes": null
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
Once running, interactive API documentation is available at:
|
||||
- **Swagger UI**: http://localhost:8000/docs
|
||||
- **ReDoc**: http://localhost:8000/redoc
|
||||
|
||||
## Testing the API
|
||||
|
||||
### Using curl
|
||||
|
||||
**Submit a report:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/emitters/report \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"unit": "SEISMO-001",
|
||||
"unit_type": "series3",
|
||||
"timestamp": "2025-11-20T10:30:00",
|
||||
"file": "event_20251120_103000.dat",
|
||||
"status": "OK"
|
||||
}'
|
||||
```
|
||||
|
||||
**Get fleet status:**
|
||||
```bash
|
||||
curl http://localhost:8000/fleet/status
|
||||
```
|
||||
|
||||
### Using Python
|
||||
|
||||
```python
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
# Submit report
|
||||
response = requests.post(
|
||||
"http://localhost:8000/emitters/report",
|
||||
json={
|
||||
"unit": "SEISMO-001",
|
||||
"unit_type": "series3",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"file": "event_20251120_103000.dat",
|
||||
"status": "OK"
|
||||
}
|
||||
)
|
||||
print(response.json())
|
||||
|
||||
# Get fleet status
|
||||
response = requests.get("http://localhost:8000/fleet/status")
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
## Data Model
|
||||
|
||||
### Emitters Table
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| id | string | Unit identifier (primary key) |
|
||||
| unit_type | string | Type of seismograph (e.g., "series3") |
|
||||
| last_seen | datetime | Last report timestamp |
|
||||
| last_file | string | Last file processed |
|
||||
| status | string | Current status: OK, Pending, Missing |
|
||||
| notes | string | Optional notes (nullable) |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
seismo-fleet-manager/
|
||||
├── main.py # FastAPI app entry point
|
||||
├── database.py # SQLAlchemy database configuration
|
||||
├── models.py # Database models
|
||||
├── routes.py # API endpoints
|
||||
├── requirements.txt # Python dependencies
|
||||
├── Dockerfile # Docker container definition
|
||||
├── docker-compose.yml # Docker Compose configuration
|
||||
├── .dockerignore # Docker ignore rules
|
||||
└── data/ # SQLite database directory (created at runtime)
|
||||
```
|
||||
|
||||
## Docker Commands
|
||||
|
||||
**Build the image:**
|
||||
```bash
|
||||
docker compose build
|
||||
```
|
||||
|
||||
**Start in foreground:**
|
||||
```bash
|
||||
docker compose up
|
||||
```
|
||||
|
||||
**Start in background:**
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
**View logs:**
|
||||
```bash
|
||||
docker compose logs -f seismo-backend
|
||||
```
|
||||
|
||||
**Restart service:**
|
||||
```bash
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
**Stop and remove containers:**
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
**Remove containers and volumes:**
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- Automated status updates based on last_seen timestamps
|
||||
- Web-based dashboard for fleet monitoring
|
||||
- Email/SMS alerts for missing units
|
||||
- Historical data tracking and reporting
|
||||
- Multi-user authentication
|
||||
- PostgreSQL support for larger deployments
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
## Version
|
||||
|
||||
0.1.0 - Initial Release
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
import os
|
||||
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///./seismo_fleet.db"
|
||||
# Ensure data directory exists
|
||||
os.makedirs("data", exist_ok=True)
|
||||
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///./data/seismo_fleet.db"
|
||||
|
||||
engine = create_engine(
|
||||
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
|
||||
|
||||
23
docker-compose.yml
Normal file
23
docker-compose.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
seismo-backend:
|
||||
build: .
|
||||
container_name: seismo-fleet-manager
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
# Persist SQLite database
|
||||
- ./data:/app/data
|
||||
environment:
|
||||
- PYTHONUNBUFFERED=1
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
volumes:
|
||||
data:
|
||||
Reference in New Issue
Block a user