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
|
||||
REDIS_HOST_PORT=26969
|
||||
BACKEND_HOST_PORT=36969
|
||||
FRONTEND_HOST_PORT=46969
|
||||
|
||||
# PostgreSQL
|
||||
POSTGRES_DB=angelusvigil
|
||||
|
|
|
|||
|
|
@ -74,6 +74,27 @@ services:
|
|||
start_period: 10s
|
||||
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:
|
||||
image: maxmindinc/geoipupdate:latest
|
||||
container_name: vigil-geoip
|
||||
|
|
|
|||
|
|
@ -71,6 +71,24 @@ services:
|
|||
retries: 3
|
||||
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:
|
||||
vigil_dev:
|
||||
driver: bridge
|
||||
|
|
@ -79,3 +97,4 @@ volumes:
|
|||
postgres_dev:
|
||||
redis_dev:
|
||||
nginx_logs_dev:
|
||||
frontend_node_modules_dev:
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ import tsconfigPaths from 'vite-tsconfig-paths'
|
|||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, path.resolve(__dirname, '..'), '')
|
||||
const isDev = mode === 'development'
|
||||
const apiTarget =
|
||||
process.env.VITE_API_TARGET ||
|
||||
env.VITE_API_TARGET ||
|
||||
'http://localhost:8000'
|
||||
|
||||
return {
|
||||
plugins: [react(), tsconfigPaths()],
|
||||
|
|
@ -32,10 +36,15 @@ export default defineConfig(({ mode }) => {
|
|||
host: '0.0.0.0',
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: env.VITE_API_TARGET || 'http://localhost:8000',
|
||||
target: apiTarget,
|
||||
changeOrigin: true,
|
||||
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