From 154c8b664b65757d316686eb5e241da1548caddb Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Tue, 27 Jan 2026 20:14:17 +0800 Subject: [PATCH] =?UTF-8?q?fix(deploy):=20=E4=BF=AE=E5=A4=8D=20Docker=20?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E8=B7=AF=E5=BE=84=E5=92=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20Nginx=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 Dockerfile 中构建产物复制路径错误,将 `/app/playground/dist` 更正为 `/app/apps/web-antd/dist`。 优化 Nginx 配置,增加安全设置、性能调优和代理规则,并移除冗余的 MIME 类型配置。 调整公告列表列对齐方式以改善界面一致性。 --- apps/web-antd/src/views/system/notice/data.ts | 2 + scripts/deploy/Dockerfile | 42 ++-- scripts/deploy/nginx.conf | 209 ++++++++++++------ 3 files changed, 175 insertions(+), 78 deletions(-) diff --git a/apps/web-antd/src/views/system/notice/data.ts b/apps/web-antd/src/views/system/notice/data.ts index 0795aeea..4e4a7f60 100644 --- a/apps/web-antd/src/views/system/notice/data.ts +++ b/apps/web-antd/src/views/system/notice/data.ts @@ -34,6 +34,8 @@ export const columns: VxeGridProps['columns'] = [ { title: '公告标题', field: 'noticeTitle', + align: 'left', + headerAlign: 'center', }, { title: '公告类型', diff --git a/scripts/deploy/Dockerfile b/scripts/deploy/Dockerfile index 86f439f2..9bc547cf 100644 --- a/scripts/deploy/Dockerfile +++ b/scripts/deploy/Dockerfile @@ -1,37 +1,47 @@ +# ============================== +# Stage 1: 构建阶段 +# ============================== FROM node:22-slim AS builder -# --max-old-space-size +# 设置环境变量 ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" +# 增加内存限制以防止构建大型项目时 OOM ENV NODE_OPTIONS=--max-old-space-size=8192 -ENV TZ=Asia/Shanghai +# 启用 corepack 以使用 pnpm RUN npm i -g corepack WORKDIR /app -# copy package.json and pnpm-lock.yaml to workspace -COPY . /app +# 复制项目文件 +COPY . . # 安装依赖 +# --frozen-lockfile: 确保使用 lock 文件中的版本 +# --mount=type=cache: 缓存 pnpm 存储,加速后续构建 RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile -RUN pnpm run build --filter=\!./docs -RUN echo "Builder Success 🎉" +# 构建 web-antd 应用 +# 使用 filter 只构建需要的应用,避免构建整个 monorepo +RUN pnpm run build --filter=@vben/web-antd +# ============================== +# Stage 2: 生产环境运行阶段 +# ============================== FROM nginx:stable-alpine AS production -# 配置 nginx -RUN echo "types { application/javascript js mjs; }" > /etc/nginx/conf.d/mjs.conf \ - && rm -rf /etc/nginx/conf.d/default.conf - -# 复制构建产物 -COPY --from=builder /app/playground/dist /usr/share/nginx/html - -# 复制 nginx 配置 +# 清理默认配置并复制自定义 Nginx 配置 +# 这里复用了 scripts/deploy/nginx.conf,它监听 8080 端口 +RUN rm -rf /etc/nginx/conf.d/default.conf COPY --from=builder /app/scripts/deploy/nginx.conf /etc/nginx/nginx.conf -EXPOSE 8080 +# 复制构建产物到 Nginx 目录 +# Vite 默认构建输出在 apps/web-antd/dist +COPY --from=builder /app/apps/web-antd/dist /usr/share/nginx/html -# 启动 nginx +# 暴露端口 (与 nginx.conf 保持一致) +EXPOSE 80 + +# 启动 Nginx CMD ["nginx", "-g", "daemon off;"] diff --git a/scripts/deploy/nginx.conf b/scripts/deploy/nginx.conf index 8e6ab101..ebe17645 100644 --- a/scripts/deploy/nginx.conf +++ b/scripts/deploy/nginx.conf @@ -1,75 +1,160 @@ +worker_processes 1; -#user nobody; -worker_processes 1; - -#error_log logs/error.log; -#error_log logs/error.log notice; -#error_log logs/error.log info; - -#pid logs/nginx.pid; - +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; events { - worker_connections 1024; + # 可以根据业务并发量适当调高 + worker_connections 1024; } - http { - include mime.types; - default_type application/octet-stream; + include mime.types; + default_type application/octet-stream; + # 高效传输文件 + sendfile on; + # 长连接超时时间 + keepalive_timeout 65; + # 单连接最大请求数,提高长连接复用率 + keepalive_requests 100000; + # 限制body大小 + client_max_body_size 100m; + client_header_buffer_size 32k; + client_body_buffer_size 512k; + # 开启静态资源压缩 + gzip_static on; + # 连接数限制 (防御类配置) 10m 一般够用了,能存储上万 IP 的计数 + limit_conn_zone $binary_remote_addr zone=perip:10m; + limit_conn_zone $server_name zone=perserver:10m; + # 隐藏 nginx 版本号,防止暴露版本信息 + server_tokens off; - types { - application/javascript js mjs; - text/css css; - text/html html; - } + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; - sendfile on; - # tcp_nopush on; + access_log /var/log/nginx/access.log main; - #keepalive_timeout 0; - # keepalive_timeout 65; - - # gzip on; - # gzip_buffers 32 16k; - # gzip_comp_level 6; - # gzip_min_length 1k; - # gzip_static on; - # gzip_types text/plain - # text/css - # application/javascript - # application/json - # application/x-javascript - # text/xml - # application/xml - # application/xml+rss - # text/javascript; #设置压缩的文件类型 - # gzip_vary on; - - server { - listen 8080; - server_name localhost; - - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - index index.html; - # Enable CORS - add_header 'Access-Control-Allow-Origin' '*'; - add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Max-Age' 1728000; - add_header 'Content-Type' 'text/plain charset=UTF-8'; - add_header 'Content-Length' 0; - return 204; - } + upstream server { + ip_hash; + server 127.0.0.1:8080; + server 127.0.0.1:8081; } - error_page 500 502 503 504 /50x.html; - - location = /50x.html { - root /usr/share/nginx/html; + upstream monitor-admin { + server 127.0.0.1:9090; + } + + upstream snailjob-server { + server 127.0.0.1:8800; + } + + server { + listen 80; + server_name localhost; + + # https配置参考 start + #listen 443 ssl; + + # 证书直接存放 /docker/nginx/cert/ 目录下即可 更改证书名称即可 无需更改证书路径 + #ssl on; + #ssl_certificate /etc/nginx/cert/xxx.local.crt; # /etc/nginx/cert/ 为docker映射路径 不允许更改 + #ssl_certificate_key /etc/nginx/cert/xxx.local.key; # /etc/nginx/cert/ 为docker映射路径 不允许更改 + #ssl_session_timeout 5m; + #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; + #ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1; + #ssl_prefer_server_ciphers on; + # https配置参考 end + + # 演示环境配置 拦截除 GET POST 之外的所有请求 + # if ($request_method !~* GET|POST) { + # rewrite ^/(.*)$ /403; + # } + + # location = /403 { + # default_type application/json; + # return 200 '{"msg":"演示模式,不允许操作","code":500}'; + # } + + # 限制外网访问内网 actuator 相关路径 + location ~ ^(/[^/]*)?/actuator.*(/.*)?$ { + return 403; + } + + location / { + if ($request_filename ~* .*\.(?:htm|html)$) { + add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate"; + access_log on; + } + root /usr/share/nginx/html; # docker映射路径 不允许更改 + try_files $uri $uri/ /index.html; + index index.html index.htm; + } + + location /prod-api/ { + # 设置客户端请求头中的 Host 信息(保持原始 Host) + proxy_set_header Host $http_host; + # 获取客户端真实 IP + proxy_set_header X-Real-IP $remote_addr; + # 自定义头 REMOTE-HOST,记录客户端 IP + proxy_set_header REMOTE-HOST $remote_addr; + # 获取完整的客户端 IP 链(经过多级代理时) + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # 设置后端响应超时时间(这里是 24 小时,适合长连接/SSE) + proxy_read_timeout 86400s; + # SSE (Server-Sent Events) 与 WebSocket 支持参数 + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + # 禁用代理缓冲,数据直接传给客户端 + proxy_buffering off; + # 禁用代理缓存 + proxy_cache off; + proxy_pass http://server/; + } + + # https 会拦截内链所有的 http 请求 造成功能无法使用 + # 解决方案1 将 admin 服务 也配置成 https + # 解决方案2 将菜单配置为外链访问 走独立页面 http 访问 + location /admin/ { + # 设置客户端请求头中的 Host 信息(保持原始 Host) + proxy_set_header Host $http_host; + # 获取客户端真实 IP + proxy_set_header X-Real-IP $remote_addr; + # 自定义头 REMOTE-HOST,记录客户端 IP + proxy_set_header REMOTE-HOST $remote_addr; + # 获取完整的客户端 IP 链(经过多级代理时) + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # 禁用代理缓冲,数据直接传给客户端 + proxy_buffering off; + # 禁用代理缓存 + proxy_cache off; + proxy_pass http://monitor-admin/admin/; + } + + location /snail-job/ { + # 设置客户端请求头中的 Host 信息(保持原始 Host) + proxy_set_header Host $http_host; + # 获取客户端真实 IP + proxy_set_header X-Real-IP $remote_addr; + # 自定义头 REMOTE-HOST,记录客户端 IP + proxy_set_header REMOTE-HOST $remote_addr; + # 获取完整的客户端 IP 链(经过多级代理时) + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # SSE (Server-Sent Events) 与 WebSocket 支持参数 + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + # 禁用代理缓冲,直接传输给客户端 + proxy_buffering off; + # 禁用代理缓存 + proxy_cache off; + proxy_pass http://snailjob-server/snail-job/; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } } - } }