feat: dockerization

This commit is contained in:
Ante Brähler
2024-11-23 14:55:28 +00:00
parent 116aac1734
commit 739578008e
10 changed files with 173 additions and 7 deletions

17
backend/Dockerfile Normal file
View File

@@ -0,0 +1,17 @@
# Backend Dockerfile
FROM node:20
# Install ffmpeg
RUN apt-get update && apt-get install -y ffmpeg
WORKDIR /app
# Install dependencies
COPY package.json package-lock.json ./
RUN npm install
# Copy source code
COPY . .
EXPOSE 5000
CMD ["npm", "start"]

View File

@@ -19,7 +19,7 @@ const apiRouter = express.Router();
apiRouter.get('/', channelController.getChannels);
apiRouter.get('/current', channelController.getCurrentChannel);
app.use('/channels', apiRouter);
app.use('/api/channels', apiRouter);
const PORT = 5000;
const server = app.listen(PORT, () => {
@@ -51,5 +51,4 @@ io.on('connection', socket => {
ChannelSocketHandler(io, socket);
ChatSocketHandler(io, socket);
})

View File

@@ -1,6 +1,5 @@
const { ChatMessage, User } = require('../models/ChatMessage');
// At the moment, this service is not used! It is only a placeholder for future development for a persistent chat.
class ChatService {
constructor() {
this.messages = [];

View File

@@ -1,10 +1,19 @@
const fs = require('fs');
const path = require("path");
const STORAGE_PATH = process.env.STORAGE_PATH;
function clearStorage() {
fs.rmSync(STORAGE_PATH, { recursive: true, force: true });
fs.mkdirSync(STORAGE_PATH);
fs.readdir(STORAGE_PATH, (err, files) => {
if (err) throw err;
for (const file of files) {
fs.unlink(path.join(STORAGE_PATH, file), (err) => {
if (err) throw err;
});
}
});
}

44
docker-compose.yml Normal file
View File

@@ -0,0 +1,44 @@
version: "3.9"
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
args:
# Set this to the server ip/domain, if your backend is deployed on a different server
#VITE_BACKEND_URL: http://123.123.123.123:5000
VITE_BACKEND_STREAMS_PATH: /streams/playlist.m3u8
VITE_STREAM_DELAY: 20
networks:
- app-network
backend:
build:
context: ./backend
dockerfile: Dockerfile
volumes:
- streams_data:/streams
environment:
DEFAULT_CHANNEL_URL: https://mcdn.daserste.de/daserste/de/master.m3u8
STORAGE_PATH: /streams
networks:
- app-network
# Nginx Reverse Proxy
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- streams_data:/streams
ports:
- "80:80"
networks:
- app-network
volumes:
streams_data:
# Internal docker network
networks:
app-network:
driver: bridge

22
frontend/.dockerignore Normal file
View File

@@ -0,0 +1,22 @@
node_modules
npm-debug.log
yarn-error.log
build
dist
*.log
*.swp
*.swo
*.DS_Store
*.git
*.gitignore
*.gitattributes
.DS_Store
.idea
.vscode
*.zip
*.tar.gz
*.tgz
.env
.env.local
.env.*.local
.env.production

29
frontend/Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
# Frontend Dockerfile
FROM node:20 AS builder
WORKDIR /app
ARG VITE_BACKEND_URL
ARG VITE_BACKEND_STREAMS_PATH
ARG VITE_STREAM_DELAY
# Install dependencies
COPY package.json package-lock.json ./
RUN npm install
# Copy source code and build
COPY . .
ENV VITE_BACKEND_URL=$VITE_BACKEND_URL
ENV VITE_BACKEND_STREAMS_PATH=$VITE_BACKEND_STREAMS_PATH
ENV VITE_STREAM_DELAY=$VITE_STREAM_DELAY
RUN npm run build
# Serve the app using a minimal HTTP server
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -10,7 +10,7 @@ const apiService = {
* @param body - The request body (e.g. POST)
* @returns Ein Promise with the parsed JSON response to class T
*/
async request<T>(path: string, method: HttpMethod = 'GET', api_url: string = API_BASE_URL, body?: unknown): Promise<T> {
async request<T>(path: string, method: HttpMethod = 'GET', api_url: string = API_BASE_URL + '/api', body?: unknown): Promise<T> {
try {
const options: RequestInit = {
method,

View File

@@ -9,7 +9,8 @@ class SocketService {
connect() {
if (this.socket?.connected) return;
console.log('Connecting to WebSocket server');
console.log('Connecting to WebSocket server: ');
// Default Behavior: If 'VITE_BACKEND_URL' is not set, the app will use the same host name as the frontend
this.socket = io(import.meta.env.VITE_BACKEND_URL);
this.socket.on('connect', () => {

46
nginx.conf Normal file
View File

@@ -0,0 +1,46 @@
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 80;
location / {
proxy_pass http://frontend:80;
}
location /api/ {
proxy_pass http://backend:5000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /socket.io/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://backend:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /streams/ {
root /;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range';
add_header Cache-Control no-cache;
}
}
}