feat(infra): add Docker and nginx infrastructure for frontend
Dev: Vite dev server in Node 24 container with hot reload via volume mount and named volume for node_modules isolation. Prod: Multi-stage build (pnpm build → nginx) serving static files with API/WebSocket reverse proxy to backend.
This commit is contained in:
parent
17efa613bf
commit
012d849366
|
|
@ -13,6 +13,7 @@ API_KEY=changeme-generate-a-real-key
|
||||||
POSTGRES_HOST_PORT=16969
|
POSTGRES_HOST_PORT=16969
|
||||||
REDIS_HOST_PORT=26969
|
REDIS_HOST_PORT=26969
|
||||||
BACKEND_HOST_PORT=36969
|
BACKEND_HOST_PORT=36969
|
||||||
|
FRONTEND_HOST_PORT=46969
|
||||||
|
|
||||||
# PostgreSQL
|
# PostgreSQL
|
||||||
POSTGRES_DB=angelusvigil
|
POSTGRES_DB=angelusvigil
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,27 @@ services:
|
||||||
start_period: 10s
|
start_period: 10s
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: infra/docker/vite.prod
|
||||||
|
container_name: vigil-frontend
|
||||||
|
ports:
|
||||||
|
- "${FRONTEND_HOST_PORT:-80}:80"
|
||||||
|
depends_on:
|
||||||
|
backend:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- vigil_network
|
||||||
|
- certgames_net
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-qO-", "http://localhost/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
restart: always
|
||||||
|
|
||||||
geoip-updater:
|
geoip-updater:
|
||||||
image: maxmindinc/geoipupdate:latest
|
image: maxmindinc/geoipupdate:latest
|
||||||
container_name: vigil-geoip
|
container_name: vigil-geoip
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,24 @@ services:
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 15s
|
start_period: 15s
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: infra/docker/vite.dev
|
||||||
|
container_name: vigil-frontend-dev
|
||||||
|
environment:
|
||||||
|
VITE_API_TARGET: http://backend:8000
|
||||||
|
ports:
|
||||||
|
- "${FRONTEND_HOST_PORT:-46969}:5173"
|
||||||
|
volumes:
|
||||||
|
- ./frontend:/app
|
||||||
|
- frontend_node_modules_dev:/app/node_modules
|
||||||
|
depends_on:
|
||||||
|
backend:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- vigil_dev
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
vigil_dev:
|
vigil_dev:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|
@ -79,3 +97,4 @@ volumes:
|
||||||
postgres_dev:
|
postgres_dev:
|
||||||
redis_dev:
|
redis_dev:
|
||||||
nginx_logs_dev:
|
nginx_logs_dev:
|
||||||
|
frontend_node_modules_dev:
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@ import tsconfigPaths from 'vite-tsconfig-paths'
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
const env = loadEnv(mode, path.resolve(__dirname, '..'), '')
|
const env = loadEnv(mode, path.resolve(__dirname, '..'), '')
|
||||||
const isDev = mode === 'development'
|
const isDev = mode === 'development'
|
||||||
|
const apiTarget =
|
||||||
|
process.env.VITE_API_TARGET ||
|
||||||
|
env.VITE_API_TARGET ||
|
||||||
|
'http://localhost:8000'
|
||||||
|
|
||||||
return {
|
return {
|
||||||
plugins: [react(), tsconfigPaths()],
|
plugins: [react(), tsconfigPaths()],
|
||||||
|
|
@ -32,10 +36,15 @@ export default defineConfig(({ mode }) => {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: env.VITE_API_TARGET || 'http://localhost:8000',
|
target: apiTarget,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (p) => p.replace(/^\/api/, ''),
|
rewrite: (p) => p.replace(/^\/api/, ''),
|
||||||
},
|
},
|
||||||
|
'/ws': {
|
||||||
|
target: apiTarget,
|
||||||
|
ws: true,
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# ©AngelaMos | 2026
|
||||||
|
# Development Vite Dockerfile
|
||||||
|
# Hot reload with volume mounts for source code
|
||||||
|
|
||||||
|
FROM node:24-alpine
|
||||||
|
|
||||||
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY frontend/package.json ./
|
||||||
|
RUN pnpm install
|
||||||
|
|
||||||
|
COPY frontend/ .
|
||||||
|
|
||||||
|
EXPOSE 5173
|
||||||
|
|
||||||
|
CMD ["pnpm", "dev"]
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# ©AngelaMos | 2026
|
||||||
|
# Production Vite Dockerfile
|
||||||
|
# Multi-stage build: pnpm build → nginx static serving
|
||||||
|
|
||||||
|
FROM node:24-alpine AS builder
|
||||||
|
|
||||||
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY frontend/package.json ./
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
COPY frontend/ .
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
RUN rm /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
COPY infra/nginx/vigil.conf /etc/nginx/conf.d/vigil.conf
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
|
||||||
|
CMD wget -qO- http://localhost/health || exit 1
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# ©AngelaMos | 2026
|
||||||
|
# vigil.conf
|
||||||
|
|
||||||
|
upstream vigil_backend {
|
||||||
|
server backend:8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml;
|
||||||
|
gzip_min_length 256;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://vigil_backend/;
|
||||||
|
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;
|
||||||
|
proxy_read_timeout 30s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /ws/ {
|
||||||
|
proxy_pass http://vigil_backend/ws/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_read_timeout 86400s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /health {
|
||||||
|
access_log off;
|
||||||
|
return 200 'ok';
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue