build(frontend): update docker image to use production env
All checks were successful
CI / Maven unit tests (push) Successful in 14s
CI / Build and push images (push) Has been skipped
CI / Deploy to server (push) Has been skipped

This commit is contained in:
2026-08-17 18:23:21 +01:00
parent da38e21935
commit b577fd9387
12 changed files with 50 additions and 12 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -38,7 +38,7 @@ services:
depends_on:
- backend
ports:
- "5173:5173"
- "5173:80"
restart: unless-stopped
rtmp:

View File

@@ -37,7 +37,7 @@ services:
depends_on:
- backend
ports:
- "5173:5173"
- "5173:80"
restart: unless-stopped
rtmp:

View File

@@ -1,9 +1,18 @@
FROM node:20-alpine
# --- Build stage ---
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY . .
EXPOSE 5173
CMD ["npm", "run", "dev"]
RUN npm run build
# --- Production stage ---
FROM nginx:1.27-alpine AS prod
COPY --from=build /app/dist /usr/share/nginx/html
# Inject envs at runtime
COPY env.sh /docker-entrypoint.d/40-env.sh
RUN chmod +x /docker-entrypoint.d/40-env.sh
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

10
frontend/env.sh Normal file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
set -eu
cat <<EOF > /usr/share/nginx/html/env-config.js
window._env_ = {
VITE_API_URL: "${VITE_API_URL:-}",
VITE_FRONTEND_URL: "${VITE_FRONTEND_URL:-}",
VITE_GOOGLE_CLIENT_ID: "${VITE_GOOGLE_CLIENT_ID:-}"
};
EOF

View File

@@ -9,6 +9,7 @@
<link href="https://fonts.googleapis.com/css2?family=Newsreader:wght@100;200;300;400;500;600;700&family=IBM+Plex+Sans:wght@100;200;300;400;500;600;700&family=IBM+Plex+Mono:wght@100;200;300;400;500;600;700&display=swap" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="/env-config.js"></script>
<title>The VoD System</title>
</head>
<body>

View File

@@ -15,6 +15,7 @@ import EditVod from "./pages/EditVod.tsx";
import Profile from "./pages/Profile.tsx";
import StreamControl from "./pages/StreamControl.tsx";
import { GoogleOAuthProvider } from '@react-oauth/google';
import {config} from "./config.ts";
function App() {
@@ -23,7 +24,7 @@ function App() {
}, []);
return (
<GoogleOAuthProvider clientId={import.meta.env.VITE_GOOGLE_CLIENT_ID}>
<GoogleOAuthProvider clientId={config.googleClientId}>
<Router>
<Routes>
<Route element={<MainLayout />}>

View File

@@ -4,6 +4,7 @@ import { Link } from "react-router-dom";
import { useEffect, useRef, useState } from "react";
import { isThumbnailAvailable } from "../../utils/api/client.ts";
import { MoreVertical, Pencil, Trash2 } from "lucide-react";
import {config} from "../../config.ts";
type VideoCardProps = {
id: number,
@@ -19,7 +20,7 @@ type VideoCardProps = {
}
const fallbackThumbnail = "../../../public/default_thumbnail.png";
const API_URL = import.meta.env.VITE_API_URL;
const API_URL = config.apiUrl;
const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className, mediaApiPath = '/api/v1/clips', playerPath = '/video', itemLabel = 'clip' }: VideoCardProps) => {
const [timeAgo, setTimeAgo] = useState(dateToTimeAgo(stringToDate(createdAt)));

5
frontend/src/config.ts Normal file
View File

@@ -0,0 +1,5 @@
export const config = {
apiUrl: window._env_?.VITE_API_URL ?? import.meta.env.VITE_API_URL ?? '',
frontendUrl: window._env_?.VITE_FRONTEND_URL ?? import.meta.env.VITE_FRONTEND_URL ?? '',
googleClientId: window._env_?.VITE_GOOGLE_CLIENT_ID ?? import.meta.env.VITE_GOOGLE_CLIENT_ID ?? '',
};

View File

@@ -10,8 +10,9 @@ import { getJob } from "../utils/api/jobs"
import type { VideoMetadata } from "../utils/types.ts";
import Box from "../components/Box.tsx";
import MetadataBox from "../components/video/MetadataBox.tsx";
import {config} from "../config.ts";
const API_URL = import.meta.env.VITE_API_URL;
const API_URL = config.apiUrl;
const ClipEdit = () => {
const location = useLocation();

View File

@@ -1,4 +1,6 @@
const API_URL = import.meta.env.VITE_API_URL;
import {config} from "../../config.ts";
const API_URL = config.apiUrl;
class AuthError extends Error {
constructor() { super("Not authenticated"); this.name = "AuthError"; }

View File

@@ -1 +1,9 @@
/// <reference types="vite/client" />
interface Window {
_env_?: {
VITE_API_URL?: string;
VITE_FRONTEND_URL?: string;
VITE_GOOGLE_CLIENT_ID?: string;
};
}