Compare commits

..

1 Commits

Author SHA1 Message Date
64ba7f9006 Merge pull request 'Fix CORS' (#3) from prochains-changements into main
All checks were successful
Build and Push Docker Images / Build Backend Image (push) Successful in 12m50s
Build and Push Docker Images / Build Frontend Image (push) Successful in 7m10s
Reviewed-on: #3
2025-12-23 14:34:05 +01:00
10 changed files with 100 additions and 148 deletions

View File

@@ -19,6 +19,4 @@ AUDIO_LIBRARY_PATH=/path/to/your/audio/library
# Frontend # Frontend
# API URL accessed by the browser (use port 8001 since backend is mapped to 8001) # API URL accessed by the browser (use port 8001 since backend is mapped to 8001)
# For production on a remote server, set this to your server's public URL
# Example: NEXT_PUBLIC_API_URL=http://yourserver.com:8001
NEXT_PUBLIC_API_URL=http://localhost:8001 NEXT_PUBLIC_API_URL=http://localhost:8001

View File

@@ -13,6 +13,95 @@ env:
IMAGE_FRONTEND: audio-classifier-frontend IMAGE_FRONTEND: audio-classifier-frontend
jobs: jobs:
build-backend:
name: Build Backend Image
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download Essentia models
run: |
mkdir -p backend/models
cd backend/models
# Download models from Essentia
echo "Downloading Essentia models..."
# Embedding model (18 MB)
curl -L -o discogs-effnet-bs64-1.pb \
https://essentia.upf.edu/models/feature-extractors/discogs-effnet/discogs-effnet-bs64-1.pb
# Genre classifier (2 MB)
curl -L -o genre_discogs400-discogs-effnet-1.pb \
https://essentia.upf.edu/models/classification-heads/genre_discogs400/genre_discogs400-discogs-effnet-1.pb
# Genre metadata
curl -L -o genre_discogs400-discogs-effnet-1.json \
https://essentia.upf.edu/models/classification-heads/genre_discogs400/genre_discogs400-discogs-effnet-1.json
# Mood classifier (2.7 MB)
curl -L -o mtg_jamendo_moodtheme-discogs-effnet-1.pb \
https://essentia.upf.edu/models/classification-heads/mtg_jamendo_moodtheme/mtg_jamendo_moodtheme-discogs-effnet-1.pb
# Instrument classifier (2.6 MB)
curl -L -o mtg_jamendo_instrument-discogs-effnet-1.pb \
https://essentia.upf.edu/models/classification-heads/mtg_jamendo_instrument/mtg_jamendo_instrument-discogs-effnet-1.pb
# Genre classifier alternative (2.7 MB)
curl -L -o mtg_jamendo_genre-discogs-effnet-1.pb \
https://essentia.upf.edu/models/classification-heads/mtg_jamendo_genre/mtg_jamendo_genre-discogs-effnet-1.pb
ls -lh
echo "Models downloaded successfully!"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ gitea.actor }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Determine version
id: version
run: |
if [[ "${{ gitea.ref }}" == refs/tags/v* ]]; then
echo "VERSION=${GITEA_REF#refs/tags/}" >> $GITHUB_OUTPUT
else
echo "VERSION=dev-$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
fi
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ gitea.repository_owner }}/${{ env.IMAGE_BACKEND }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ startsWith(gitea.ref, 'refs/tags/v') }}
type=raw,value=dev,enable=${{ gitea.ref == 'refs/heads/main' }}
type=sha,prefix=dev-,format=short,enable=${{ gitea.ref == 'refs/heads/main' }}
- name: Build and push backend
uses: docker/build-push-action@v5
with:
context: .
file: ./backend/Dockerfile
push: true
build-args: |
VERSION=${{ steps.version.outputs.VERSION }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ gitea.repository_owner }}/${{ env.IMAGE_BACKEND }}:buildcache
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ gitea.repository_owner }}/${{ env.IMAGE_BACKEND }}:buildcache,mode=max
build-frontend: build-frontend:
name: Build Frontend Image name: Build Frontend Image
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -204,20 +204,13 @@ cd Audio-Classifier
# Chemin vers musique # Chemin vers musique
AUDIO_LIBRARY_PATH=/mnt/musique AUDIO_LIBRARY_PATH=/mnt/musique
# URL publique de l'API (IMPORTANT pour le frontend) # Domaine public
# Cette URL est utilisée par le navigateur pour accéder à l'API CORS_ORIGINS=http://votre-domaine.com,https://votre-domaine.com
# Remplacer par votre domaine ou IP publique + port 8001
NEXT_PUBLIC_API_URL=https://votre-serveur.com:8001
# Domaine public pour CORS (doit inclure l'URL du frontend)
CORS_ORIGINS=https://votre-domaine.com,https://votre-domaine.com:3000
# Credentials BDD (sécurisés !) # Credentials BDD (sécurisés !)
POSTGRES_PASSWORD=motdepasse_fort_aleatoire POSTGRES_PASSWORD=motdepasse_fort_aleatoire
``` ```
**Important :** Le frontend utilise maintenant une configuration **runtime**, ce qui signifie que vous pouvez changer `NEXT_PUBLIC_API_URL` dans le fichier `.env` et redémarrer les containers sans avoir à rebuilder les images.
4. **Démarrer** : 4. **Démarrer** :
```bash ```bash
docker-compose up -d docker-compose up -d

View File

@@ -19,7 +19,7 @@ services:
restart: unless-stopped restart: unless-stopped
backend: backend:
image: git.benoitsz.com/benoit/audio-classifier-backend:dev image: git.benoitsz.com/benoit/audio-classifier-backend:latest
container_name: audio_classifier_api container_name: audio_classifier_api
depends_on: depends_on:
postgres: postgres:
@@ -38,12 +38,12 @@ services:
restart: unless-stopped restart: unless-stopped
frontend: frontend:
image: git.benoitsz.com/benoit/audio-classifier-frontend:dev image: git.benoitsz.com/benoit/audio-classifier-frontend:latest
container_name: audio_classifier_ui container_name: audio_classifier_ui
environment: environment:
# In production, set NEXT_PUBLIC_API_URL to your server's public URL # Use localhost:8001 because the browser (client-side) needs to access the API
# Example: NEXT_PUBLIC_API_URL=https://yourserver.com:8001 # The backend is mapped to port 8001 on the host machine
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8001} NEXT_PUBLIC_API_URL: http://localhost:8001
ports: ports:
- "3000:3000" - "3000:3000"
depends_on: depends_on:

View File

@@ -12,19 +12,15 @@ RUN npm ci
# Copy application code # Copy application code
COPY frontend/ . COPY frontend/ .
# Build argument for API URL (used for default build) # Build argument for API URL
ARG NEXT_PUBLIC_API_URL=http://localhost:8001 ARG NEXT_PUBLIC_API_URL=http://localhost:8001
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
# Build the application # Build the application
RUN npm run build RUN npm run build
# Copy runtime config generation script
COPY frontend/generate-config.sh /app/generate-config.sh
RUN chmod +x /app/generate-config.sh
# Expose port # Expose port
EXPOSE 3000 EXPOSE 3000
# Generate runtime config and start the application # Start the application
CMD ["/bin/sh", "-c", "/app/generate-config.sh && npm start"] CMD ["npm", "start"]

View File

@@ -1,93 +0,0 @@
# Frontend - Audio Classifier
Frontend Next.js pour Audio Classifier avec configuration runtime.
## Configuration Runtime
Le frontend utilise un système de **configuration runtime** qui permet de changer l'URL de l'API sans rebuilder l'image Docker.
### Comment ça fonctionne
1. Au démarrage du container, le script `generate-config.sh` génère un fichier `/app/public/config.js`
2. Ce fichier contient l'URL de l'API basée sur la variable `NEXT_PUBLIC_API_URL`
3. Le fichier est chargé dans le navigateur via `<Script src="/config.js">`
4. Le code API lit la configuration depuis `window.__RUNTIME_CONFIG__.API_URL`
### Développement Local
```bash
# Installer les dépendances
npm install
# Créer un fichier .env.local
echo "NEXT_PUBLIC_API_URL=http://localhost:8001" > .env.local
# Lancer en mode dev
npm run dev
```
### Production avec Docker
```bash
# Build l'image
docker build -t audio-classifier-frontend -f frontend/Dockerfile .
# Lancer avec une URL personnalisée
docker run -p 3000:3000 \
-e NEXT_PUBLIC_API_URL=https://mon-serveur.com:8001 \
audio-classifier-frontend
```
### Docker Compose
```yaml
frontend:
image: audio-classifier-frontend
environment:
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8001}
ports:
- "3000:3000"
```
## Structure
```
frontend/
├── app/ # Pages Next.js (App Router)
│ ├── layout.tsx # Layout principal (charge config.js)
│ └── page.tsx # Page d'accueil
├── components/ # Composants React
├── lib/ # Utilitaires
│ ├── api.ts # Client API (lit la config runtime)
│ └── types.ts # Types TypeScript
├── public/ # Fichiers statiques
│ └── config.js # Configuration runtime (généré au démarrage)
├── generate-config.sh # Script de génération de config
└── Dockerfile # Image Docker de production
```
## Variables d'Environnement
- `NEXT_PUBLIC_API_URL` : URL de l'API backend (ex: `https://api.example.com:8001`)
## Troubleshooting
### L'API n'est pas accessible
Vérifiez que :
1. La variable `NEXT_PUBLIC_API_URL` est correctement définie
2. Le fichier `/app/public/config.js` existe dans le container
3. Le navigateur peut accéder à l'URL de l'API (pas de CORS, firewall, etc.)
### Voir la configuration active
Ouvrez la console du navigateur et tapez :
```javascript
console.log(window.__RUNTIME_CONFIG__)
```
### Vérifier la config dans le container
```bash
docker exec audio_classifier_ui cat /app/public/config.js
```

View File

@@ -2,7 +2,6 @@ import type { Metadata } from "next"
import { Inter } from "next/font/google" import { Inter } from "next/font/google"
import "./globals.css" import "./globals.css"
import { QueryProvider } from "@/components/providers/QueryProvider" import { QueryProvider } from "@/components/providers/QueryProvider"
import Script from "next/script"
const inter = Inter({ subsets: ["latin"] }) const inter = Inter({ subsets: ["latin"] })
@@ -18,9 +17,6 @@ export default function RootLayout({
}) { }) {
return ( return (
<html lang="en"> <html lang="en">
<head>
<Script src="/config.js" strategy="beforeInteractive" />
</head>
<body className={inter.className}> <body className={inter.className}>
<QueryProvider> <QueryProvider>
{children} {children}

View File

@@ -1,15 +0,0 @@
#!/bin/sh
# Generate runtime configuration file
echo "Generating runtime configuration..."
echo "API URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8001}"
cat > /app/public/config.js << EOF
// Runtime configuration generated at container startup
window.__RUNTIME_CONFIG__ = {
API_URL: '${NEXT_PUBLIC_API_URL:-http://localhost:8001}'
};
EOF
echo "Configuration generated successfully!"
cat /app/public/config.js

View File

@@ -14,15 +14,7 @@ import type {
FilterParams, FilterParams,
} from './types' } from './types'
// Get API URL from runtime config (injected at container startup) or fallback to env var const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
function getApiUrl(): string {
if (typeof window !== 'undefined' && (window as any).__RUNTIME_CONFIG__) {
return (window as any).__RUNTIME_CONFIG__.API_URL
}
return process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
}
const API_BASE_URL = getApiUrl()
const apiClient = axios.create({ const apiClient = axios.create({
baseURL: API_BASE_URL, baseURL: API_BASE_URL,

View File

@@ -1,4 +0,0 @@
// This file will be overwritten at container startup
window.__RUNTIME_CONFIG__ = {
API_URL: 'http://localhost:8001'
};