Etappe 1: Container-Infrastruktur + udev-Erkennung
- Docker Compose mit 5 Containern (api, worker, ui, postgres, redis) - Basis-Dockerfiles für FastAPI, Celery, React/Vite, PostgreSQL, Redis - udev-Regel + Python-Daemon für Disc-Einwurf-Erkennung - Device-Resolver (UUID/Serial → /dev/disc/<uuid>) - Celery-Worker mit Dummy-Job-Task (Disc-Erkennung) - .env.example mit Umgebungsvariablen - .gitignore für Docker, .env, node_modules - README, SAVEPOINT, ROADMAP aktualisiert
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install --no-cache-dir \
|
||||
fastapi==0.115.0 \
|
||||
uvicorn==0.30.0 \
|
||||
psycopg2-binary==2.9.9 \
|
||||
pydantic==2.9.0 \
|
||||
python-dotenv==1.0.1
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY main.py .
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
@@ -0,0 +1,23 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
import os
|
||||
|
||||
app = FastAPI(
|
||||
title="Rippy API",
|
||||
description="API für das automatische Ripping-System",
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
return {"status": "ok", "service": "api"}
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {
|
||||
"name": "Rippy",
|
||||
"version": "1.0.0",
|
||||
"description": "Automatisches Ripping-System für CD, DVD und Blu-ray"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fastapi==0.115.0
|
||||
uvicorn==0.30.0
|
||||
psycopg2-binary==2.9.9
|
||||
pydantic==2.9.0
|
||||
python-dotenv==1.0.1
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM postgres:16-slim
|
||||
|
||||
COPY init.sql /docker-entrypoint-initdb.d/
|
||||
|
||||
EXPOSE 5432
|
||||
@@ -0,0 +1,3 @@
|
||||
CREATE DATABASE rippy;
|
||||
CREATE USER rippy WITH PASSWORD 'rippy123';
|
||||
GRANT ALL PRIVILEGES ON DATABASE rippy TO rippy;
|
||||
@@ -0,0 +1,5 @@
|
||||
FROM redis:7-alpine
|
||||
|
||||
COPY redis.conf /usr/local/etc/redis/redis.conf
|
||||
|
||||
CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]
|
||||
@@ -0,0 +1,6 @@
|
||||
appendonly yes
|
||||
appendfsync everysec
|
||||
timeout 0
|
||||
tcp-keepalive 300
|
||||
loglevel notice
|
||||
databases 16
|
||||
@@ -0,0 +1,14 @@
|
||||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache curl
|
||||
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm ci --only=production 2>/dev/null || npm install --only=production
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["vite", "--host", "0.0.0.0", "--port", "80"]
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "rippy-ui",
|
||||
"version": "1.0.0",
|
||||
"description": "Rippy Web UI",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.4.0"
|
||||
},
|
||||
"packageManager": "npm@10.8.0"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
export default defineConfig({
|
||||
root: './',
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
assetsDir: 'assets'
|
||||
},
|
||||
server: {
|
||||
port: 80,
|
||||
host: true
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install --no-cache-dir \
|
||||
celery==5.4.0 \
|
||||
redis==5.0.7 \
|
||||
psycopg2-binary==2.9.9 \
|
||||
python-dotenv==1.0.1
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD ["celery", "-A", "celery_app", "worker", "--loglevel=info", "--pool=solo"]
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from celery import Celery
|
||||
import os
|
||||
|
||||
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0")
|
||||
|
||||
celery_app = Celery(
|
||||
"rippy_worker",
|
||||
broker=REDIS_URL,
|
||||
backend=REDIS_URL,
|
||||
include=["tasks"]
|
||||
)
|
||||
|
||||
celery_app.conf.update(
|
||||
task_serializer="json",
|
||||
accept_content=["json"],
|
||||
result_serializer="json",
|
||||
timezone="UTC",
|
||||
enable_utc=True,
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
celery==5.4.0
|
||||
redis==5.0.7
|
||||
psycopg2-binary==2.9.9
|
||||
python-dotenv==1.0.1
|
||||
@@ -0,0 +1,15 @@
|
||||
import os
|
||||
from celery_app import celery_app
|
||||
|
||||
|
||||
@celery_app.task(bind=True, name="worker.tasks.detect_disc")
|
||||
def detect_disc(self, device_path: str, disc_type: str):
|
||||
"""Dummy-Disk-Erkennungstask."""
|
||||
print(f"Disc erkannt: {disc_type}, Device: {device_path}")
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": f"Disc erkannt: {disc_type}",
|
||||
"device_path": device_path,
|
||||
"disc_type": disc_type
|
||||
}
|
||||
Reference in New Issue
Block a user