Add Dockerfile for back and front, Set the runtime env for front

This commit is contained in:
dvirlabs 2025-08-08 12:31:59 +03:00
parent 1dd1b96646
commit 9cfc07a510
14 changed files with 94 additions and 31 deletions

View File

@ -1,29 +1,37 @@
FROM python:3.11-slim
# ---- Base ----
FROM python:3.11-slim-bookworm
# Install ffmpeg + curl and download latest yt-dlp binary
RUN apt update && \
apt install -y curl ffmpeg && \
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp && \
chmod a+rx /usr/local/bin/yt-dlp && \
apt clean && rm -rf /var/lib/apt/lists/*
# עדכון מערכת והתקנת FFmpeg (כולל ffprobe)
RUN apt-get update \
&& apt-get install -y --no-install-recommends ffmpeg \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
# הגדרות סביבת עבודה בסיסיות
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
# ספריית האפליקציה
WORKDIR /app
# Copy project files
COPY . .
# Install Python dependencies
# התקנת תלויות
# (משתמש ב־requirements.txt שהבאת)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Create volume path (optional - will be mounted later in K8s)
RUN mkdir -p /music
# קבצי האפליקציה
COPY . .
# Declare env var for clean override later in Helm
ENV MUSIC_DIR=/music
# תיקיית המוזיקה (הקוד גם יוצר אותה, אבל נגדיר כ־VOLUME לנוחות)
VOLUME ["/app/music"]
# Expose FastAPI port
# פורט האפליקציה
EXPOSE 8000
# Start app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
# ריצה תחת משתמש לא־רות
RUN useradd -ms /bin/bash appuser && chown -R appuser:appuser /app
USER appuser
# הפעלה
# אם תרצה workers: הוסף --workers 2 (או לפי הצורך)
ENTRYPOINT ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--proxy-headers"]

6
frontend/.dockerignore Normal file
View File

@ -0,0 +1,6 @@
node_modules
dist
.git
.gitignore
npm-debug.log
.DS_Store

View File

@ -0,0 +1,10 @@
#!/bin/sh
set -eu
TEMPLATE="/etc/env/env.js.template"
TARGET="/usr/share/nginx/html/env.js"
VITE_API_URL="${VITE_API_URL:-http://localhost:8000}"
echo "[entrypoint] Generating runtime env -> $TARGET"
sed "s|\$VITE_API_URL|${VITE_API_URL}|g" "$TEMPLATE" > "$TARGET"
echo "[entrypoint] Done."

16
frontend/Dockerfile Normal file
View File

@ -0,0 +1,16 @@
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm install --legacy-peer-deps
COPY . .
RUN npm run build
FROM nginx:alpine
RUN apk add --no-cache dos2unix gettext
COPY --from=builder /app/dist /usr/share/nginx/html
COPY public/env.js.template /etc/env/env.js.template
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY 10-generate-env.sh /docker-entrypoint.d/10-generate-env.sh
RUN dos2unix /docker-entrypoint.d/10-generate-env.sh && chmod +x /docker-entrypoint.d/10-generate-env.sh
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<title>Tunedrop</title>
<script src="/env.js"></script>
</head>
<body>
<div id="root"></div>

16
frontend/nginx.conf Normal file
View File

@ -0,0 +1,16 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri /index.html;
}
location = /env.js {
alias /usr/share/nginx/html/env.js;
add_header Cache-Control "no-store";
}
}

View File

@ -0,0 +1,4 @@
// Replaced at container start
window.__ENV = {
VITE_API_URL: "$VITE_API_URL"
};

View File

@ -1,16 +1,19 @@
const BASE_URL = import.meta.env.VITE_API_URL || "http://localhost:8000";
const runtimeBase = typeof window !== "undefined" && window.__ENV && window.__ENV.VITE_API_URL;
const buildTimeBase = import.meta.env?.VITE_API_URL;
const BASE_URL = runtimeBase || buildTimeBase || "http://localhost:8000";
export async function downloadSong(query) {
const response = await fetch(`${BASE_URL}/download?query=${encodeURIComponent(query)}`);
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || "Unknown error");
const res = await fetch(`${BASE_URL}/download?query=${encodeURIComponent(query)}`);
if (!res.ok) {
let detail = "Unknown error";
try { detail = (await res.json()).detail || detail; } catch {}
throw new Error(detail);
}
return await response.json();
return res.json();
}
export async function getDownloadedSongs() {
const response = await fetch(`${BASE_URL}/songs`);
if (!response.ok) throw new Error("Failed to fetch songs");
return await response.json();
const res = await fetch(`${BASE_URL}/songs`);
if (!res.ok) throw new Error("Failed to fetch songs");
return res.json();
}