feat: NCS-75 Frontend Deployment Dockerfile (#4)

Co-authored-by: shahdlala66 <shahd.lala66@gmail.com>
Reviewed-on: #4
Co-authored-by: Shahd Lala <shosho996@blackhole.local>
Co-committed-by: Shahd Lala <shosho996@blackhole.local>
This commit was merged in pull request #4.
This commit is contained in:
2026-05-12 11:21:04 +02:00
committed by Janis
parent ff75c8ce2f
commit bd7ec581e3
10 changed files with 113 additions and 5 deletions
+25
View File
@@ -0,0 +1,25 @@
FROM --platform=$BUILDPLATFORM node:lts-alpine3.23 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM --platform=$TARGETPLATFORM nginx:stable-alpine AS production
RUN apk add --no-cache gettext
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app/dist/nowchess-frontend/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY public/env.template.js /usr/share/nginx/html/env.template.js
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
EXPOSE 80
ENTRYPOINT ["/docker-entrypoint.sh"]
+11
View File
@@ -58,6 +58,14 @@
],
"outputHashing": "all"
},
"staging": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.staging.ts"
}
]
},
"development": {
"fileReplacements": [
{
@@ -83,6 +91,9 @@
"production": {
"buildTarget": "nowchess-frontend:build:production"
},
"staging": {
"buildTarget": "nowchess-frontend:build:staging"
},
"development": {
"buildTarget": "nowchess-frontend:build:development"
}
+18
View File
@@ -0,0 +1,18 @@
#!/bin/sh
set -e
# Replace placeholders in env.template.js with environment variables and write env.js
TEMPLATE_PATH="/usr/share/nginx/html/env.template.js"
TARGET_PATH="/usr/share/nginx/html/env.js"
if [ -f "$TEMPLATE_PATH" ]; then
echo "Rendering runtime config from $TEMPLATE_PATH"
echo "Using environment variables:"
printenv
echo "----"
envsubst < "$TEMPLATE_PATH" > "$TARGET_PATH"
else
echo "No runtime template found at $TEMPLATE_PATH, skipping"
fi
exec nginx -g 'daemon off;'
+22
View File
@@ -0,0 +1,22 @@
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /env.js {
root /usr/share/nginx/html;
default_type application/javascript;
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
+2 -1
View File
@@ -4,7 +4,8 @@
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"build": "ng build --configuration production",
"build:staging": "ng build --configuration staging",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
+4
View File
@@ -0,0 +1,4 @@
window.__RUNTIME_CONFIG__ = {
API_URL: "${API_URL}",
WEBSOCKET_URL: "${WEBSOCKET_URL}"
};
+11
View File
@@ -0,0 +1,11 @@
/**
* Load runtime configuration from window.__RUNTIME_CONFIG__
* This is injected by docker-entrypoint.sh at container startup
*/
export function loadRuntimeConfig() {
const config = (window as any).__RUNTIME_CONFIG__ || {};
return {
apiUrl: config.API_URL || '',
wsUrl: config.WEBSOCKET_URL || 'ws://localhost:8080'
};
}
+11
View File
@@ -0,0 +1,11 @@
import { loadRuntimeConfig } from '../app/core/config.loader';
const runtimeConfig = loadRuntimeConfig();
export const environment = {
production: true,
apiBaseUrl: runtimeConfig.apiUrl || 'https://st.nowchess.janis-eccarius.de',
accountServiceUrl: runtimeConfig.apiUrl || 'https://st.nowchess.janis-eccarius.de',
wsBaseUrl: runtimeConfig.wsUrl || 'wss://st.nowchess.janis-eccarius.de',
apiPath: '/api/board/game'
};
+8 -4
View File
@@ -1,7 +1,11 @@
import { loadRuntimeConfig } from '../app/core/config.loader';
const runtimeConfig = loadRuntimeConfig();
export const environment = {
production: true,
apiBaseUrl: '',
accountServiceUrl: '',
wsBaseUrl: 'ws://localhost:8080',
production: false,
apiBaseUrl: runtimeConfig.apiUrl || '',
accountServiceUrl: runtimeConfig.apiUrl || '',
wsBaseUrl: runtimeConfig.wsUrl,
apiPath: '/api/board/game'
};
+1
View File
@@ -6,6 +6,7 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script src="/env.js" defer></script>
</head>
<body>
<app-root></app-root>