worker_processes auto; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; # 对齐 application.yml 的 spring.servlet.multipart.max-request-size(25M) client_max_body_size 25M; sendfile on; keepalive_timeout 65; gzip on; # text/javascript 与 application/javascript 均列,兼容不同版本 mime.types 对 .js 的映射 gzip_types text/css text/javascript application/javascript application/json image/svg+xml; upstream crm_app { server crm-app:8080; } # 缩略图代理缓存区(10MB 内存索引,100MB 磁盘,1天不访问则淘汰) proxy_cache_path /var/cache/nginx/thumbnails levels=1:2 keys_zone=thumb_cache:10m max_size=100m inactive=1d use_temp_path=off; server { listen 80; server_name _; # ========== 静态文档页(浏览器缓存 1 天) ========== location /crm-api/docs/ { alias /usr/share/nginx/docs/; index crm-api-docs-documentation.html; expires 1d; add_header Cache-Control "public, max-age=86400"; } location = /crm-api/docs { return 301 /crm-api/docs/; } location /docs/ { alias /usr/share/nginx/docs/; index crm-api-docs-documentation.html; expires 1d; add_header Cache-Control "public, max-age=86400"; } location = /docs { return 301 /docs/; } # ========== 缩略图(nginx 代理缓存) ========== # 后端对 READY 缩略图返回 Cache-Control: max-age=86400 → nginx 缓存 # 后端对占位图返回 Cache-Control: no-cache → nginx 不缓存(尊重后端) # 带 /crm-api 前缀 location /crm-api/api/file/thumbnail { proxy_pass http://crm_app/api/file/thumbnail; proxy_cache thumb_cache; proxy_cache_key "$scheme$request_method$host$request_uri"; proxy_cache_valid 200 1d; proxy_cache_valid 404 1m; proxy_cache_use_stale error timeout updating; add_header X-Cache-Status $upstream_cache_status; proxy_set_header Host $host; } # 不带前缀 location /api/file/thumbnail { proxy_pass http://crm_app; proxy_cache thumb_cache; proxy_cache_key "$scheme$request_method$host$request_uri"; proxy_cache_valid 200 1d; proxy_cache_valid 404 1m; proxy_cache_use_stale error timeout updating; add_header X-Cache-Status $upstream_cache_status; proxy_set_header Host $host; } # ========== 带 /crm-api 前缀的 API(去掉前缀转发) ========== location /crm-api/ { proxy_pass http://crm_app/; 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 300s; proxy_send_timeout 300s; proxy_request_buffering off; } # ========== 不带前缀的 API 直接转发 ========== # 前端部署后 location / 让给静态资源,API 透传职责由本块承接(原样传递,不重写 URI) location /api/ { proxy_pass http://crm_app; 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 300s; proxy_send_timeout 300s; proxy_request_buffering off; } # ========== 前端静态资源(SPA) ========== # 宿主机 nginx/html 挂载到 /usr/share/nginx/html(见 docker-compose.yml) # 前端更新:替换宿主机 nginx/html 目录内容即可,无需重启容器 location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } # index.html 不缓存:发版后浏览器立刻拿到新版(引用新 hash 的 js/css) location = /index.html { root /usr/share/nginx/html; add_header Cache-Control "no-cache"; } # 带 hash 的构建产物长缓存 location /assets/ { root /usr/share/nginx/html; expires 30d; add_header Cache-Control "public, immutable"; } } }