mirror of
https://github.com/wahyd4/you-music.git
synced 2026-08-09 05:06:44 +10:00
Make docker image work
This commit is contained in:
+5
-1
@@ -47,6 +47,7 @@ EXPOSE 8000
|
|||||||
|
|
||||||
# Environment variables
|
# Environment variables
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV PYTHONPATH=/app/backend
|
||||||
ENV DATABASE_URL=sqlite+aiosqlite:///./data/youmusic.db
|
ENV DATABASE_URL=sqlite+aiosqlite:///./data/youmusic.db
|
||||||
ENV MUSIC_DIR=/app/data/music
|
ENV MUSIC_DIR=/app/data/music
|
||||||
ENV UPLOAD_DIR=/app/data/uploads
|
ENV UPLOAD_DIR=/app/data/uploads
|
||||||
@@ -57,5 +58,8 @@ ENV BASE_DIR=/app
|
|||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
CMD curl -f http://localhost:8000/ || exit 1
|
CMD curl -f http://localhost:8000/ || exit 1
|
||||||
|
|
||||||
|
# Set working directory to backend
|
||||||
|
WORKDIR /app/backend
|
||||||
|
|
||||||
# Run the application
|
# Run the application
|
||||||
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
|
|||||||
+63
-7
@@ -1,8 +1,10 @@
|
|||||||
import os
|
import os
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from pathlib import Path
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
from app.api import music, playlist, download, search, stream, artist
|
from app.api import music, playlist, download, search, stream, artist
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.db.session import init_db
|
from app.db.session import init_db
|
||||||
@@ -11,11 +13,34 @@ from app.db.session import init_db
|
|||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
# Startup
|
# Startup
|
||||||
|
print("=" * 80)
|
||||||
|
print("🎵 YouMusic Starting Up")
|
||||||
|
print("=" * 80)
|
||||||
|
print(f"📂 BASE_DIR: {settings.BASE_DIR}")
|
||||||
|
print(f"📂 MUSIC_DIR: {settings.MUSIC_DIR}")
|
||||||
|
print(f"📂 UPLOAD_DIR: {settings.UPLOAD_DIR}")
|
||||||
|
print(f"📂 TEMP_DIR: {settings.TEMP_DIR}")
|
||||||
|
print(f"📂 DATABASE: {settings.DATABASE_URL}")
|
||||||
|
|
||||||
|
cache_dir = os.path.join(settings.BASE_DIR, "data", "cache")
|
||||||
|
artist_cache_dir = os.path.join(cache_dir, "artists")
|
||||||
|
artist_images_dir = os.path.join(cache_dir, "artist_images")
|
||||||
|
|
||||||
|
print(f"📂 CACHE_DIR: {cache_dir}")
|
||||||
|
print(f"📂 ARTIST_CACHE: {artist_cache_dir}")
|
||||||
|
print(f"📂 ARTIST_IMAGES: {artist_images_dir}")
|
||||||
|
print(f"🎬 FFMPEG: {settings.FFMPEG_LOCATION}")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
os.makedirs(settings.MUSIC_DIR, exist_ok=True)
|
os.makedirs(settings.MUSIC_DIR, exist_ok=True)
|
||||||
os.makedirs(settings.UPLOAD_DIR, exist_ok=True)
|
os.makedirs(settings.UPLOAD_DIR, exist_ok=True)
|
||||||
os.makedirs(os.path.join(settings.BASE_DIR, "data", "cache"), exist_ok=True)
|
os.makedirs(cache_dir, exist_ok=True)
|
||||||
os.makedirs(os.path.join(settings.BASE_DIR, "data", "cache", "artist_images"), exist_ok=True)
|
os.makedirs(artist_cache_dir, exist_ok=True)
|
||||||
|
os.makedirs(artist_images_dir, exist_ok=True)
|
||||||
await init_db()
|
await init_db()
|
||||||
|
|
||||||
|
print("✅ All directories created and database initialized")
|
||||||
|
print("=" * 80)
|
||||||
yield
|
yield
|
||||||
# Shutdown
|
# Shutdown
|
||||||
|
|
||||||
@@ -53,16 +78,47 @@ app.include_router(stream.router, prefix="/api", tags=["stream"])
|
|||||||
app.include_router(artist.router, prefix="/api/artists", tags=["artists"])
|
app.include_router(artist.router, prefix="/api/artists", tags=["artists"])
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
# Health check endpoint (must be before catch-all route)
|
||||||
async def root():
|
|
||||||
return {"message": "YouMusic API is running"}
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
async def health():
|
async def health():
|
||||||
return {"status": "healthy"}
|
return {"status": "healthy"}
|
||||||
|
|
||||||
|
|
||||||
|
# Mount frontend static files (built React app)
|
||||||
|
static_dir = Path(__file__).parent / "static"
|
||||||
|
if static_dir.exists():
|
||||||
|
app.mount("/assets", StaticFiles(directory=str(static_dir / "assets")), name="assets")
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
async def serve_frontend():
|
||||||
|
"""Serve the React frontend"""
|
||||||
|
index_file = static_dir / "index.html"
|
||||||
|
if index_file.exists():
|
||||||
|
return FileResponse(index_file)
|
||||||
|
return {"message": "YouMusic API is running (frontend not built)"}
|
||||||
|
|
||||||
|
@app.get("/{full_path:path}")
|
||||||
|
async def serve_spa(full_path: str):
|
||||||
|
"""Serve React app for all non-API routes (SPA routing)"""
|
||||||
|
# Skip API routes, health check, and static assets
|
||||||
|
if full_path.startswith(("api/", "music/", "cache/", "assets/", "health", "docs", "redoc", "openapi.json")):
|
||||||
|
return {"error": "Not found"}
|
||||||
|
|
||||||
|
# For all other routes, serve index.html (React Router handles client-side routing)
|
||||||
|
index_file = static_dir / "index.html"
|
||||||
|
if index_file.exists():
|
||||||
|
return FileResponse(index_file)
|
||||||
|
return {"error": "Frontend not found"}
|
||||||
|
else:
|
||||||
|
@app.get("/")
|
||||||
|
async def root():
|
||||||
|
return {"message": "YouMusic API is running (frontend not built)"}
|
||||||
|
|
||||||
|
@app.get("/health")
|
||||||
|
async def health_no_frontend():
|
||||||
|
return {"status": "healthy"}
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import uvicorn
|
import uvicorn
|
||||||
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
||||||
|
|||||||
+2
-1
@@ -7,7 +7,8 @@ services:
|
|||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
- ./backend:/app/backend
|
# Note: Do not mount ./backend in production - it overwrites the built image
|
||||||
|
# For development, use ./dev.sh instead
|
||||||
environment:
|
environment:
|
||||||
- DATABASE_URL=sqlite+aiosqlite:////app/data/youmusic.db
|
- DATABASE_URL=sqlite+aiosqlite:////app/data/youmusic.db
|
||||||
- MUSIC_DIR=/app/data/music
|
- MUSIC_DIR=/app/data/music
|
||||||
|
|||||||
Reference in New Issue
Block a user