通过 HTTP 提供 S3/MinIO 公共 Angular 单页应用的 nginx Docker 配置
这是我的 nginx 配置,可自动通过 HTTP 提供公共 S3/MinIO Angular 单页应用。它预期与提供 HTTPS 的外部代理配合使用。在我的场景中,这个代理是 Traefik。有关我的配置详情,请参阅使用 Let’s Encrypt Cloudflare DNS-01、TLS-ALPN-01 和 HTTP-01 挑战的简单 Traefik docker-compose 设置。
此配置变体不包含通过 S3 提供 @angular/localize 多语言配置的内容。有关提供多语言静态站点并带有自动选择逻辑的 nginx 示例,请参阅如何使用 nginx 提供 @angular/localize 多语言国际化 Angular UI。
nginx.conf
你通常只需要更改以下变量:
nginx_minio_spa.conf
# 将此更改为你 S3 存储桶的名称。确保它已设置为公开!
set $bucket "/my-bucket";
# 将此更改为你 MinIO/S3 的主机(不含协议)
set $minio_host "minio.mydomain.com";完整配置:
nginx.conf
# /etc/nginx/nginx.conf
worker_processes auto;
events { worker_connections 1024; }
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
# 通过 Docker 主机进行 DNS 解析(Docker 内嵌 DNS)
resolver 127.0.0.11 valid=24h ipv6=off;
resolver_timeout 5s;
# 对文本资源可选的 gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_types
text/plain text/css application/javascript application/json
application/xml application/rss+xml image/svg+xml;
# 磁盘缓存(根据需要调整大小)
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:100m max_size=10g inactive=30d use_temp_path=off;
server {
listen 80;
server_name _; # Traefik 路由到这里
# 存储桶路径的便捷变量
# 存储桶路径和 MinIO 主机的便捷变量
set $bucket "/my-bucket";
# 将此更改为你 MinIO/S3 的主机(不含协议)
set $minio_host "minio.techoverflow.net";
# 拦截上游的 404/403 并路由到 SPA
error_page 404 = @spa;
error_page 403 = @spa;
# 精确匹配根路径 "/" -> 提供 index.html
location = / {
proxy_pass https://$minio_host$bucket/index.html;
proxy_set_header Host $minio_host;
proxy_ssl_server_name on;
proxy_buffering on;
proxy_cache STATIC;
proxy_cache_key $scheme$proxy_host$uri$is_args$args;
# 不在浏览器中缓存 SPA HTML(可选)
add_header Cache-Control "no-cache, must-revalidate" always;
# 拦截错误,使 error_page 即使在缓存层也能生效
proxy_intercept_errors on;
# 避免缓存上游错误
proxy_no_cache $upstream_status = 404;
proxy_cache_bypass $upstream_status = 404;
proxy_no_cache $upstream_status = 403;
proxy_cache_bypass $upstream_status = 403;
add_header X-Cache-Status $upstream_cache_status always;
}
# 其他所有请求的统一处理
location / {
proxy_pass https://$minio_host$bucket$uri$is_args$args;
proxy_set_header Host $minio_host;
proxy_ssl_server_name on;
proxy_buffering on;
proxy_http_version 1.1;
proxy_cache STATIC;
proxy_cache_key $scheme$proxy_host$uri$is_args$args;
# 成功响应的统一 TTL
proxy_cache_valid 200 301 302 24h;
# 不缓存上游错误(防止提供纯 NGINX 404)
proxy_no_cache $upstream_status = 404;
proxy_cache_bypass $upstream_status = 404;
proxy_no_cache $upstream_status = 403;
proxy_cache_bypass $upstream_status = 403;
# 可选的浏览器缓存(如果你对资源进行版本控制则启用)
# add_header Cache-Control "public, max-age=86400, immutable" always;
add_header X-Cache-Status $upstream_cache_status always;
# 确保在源返回 404/403 时触发 SPA 回退
proxy_intercept_errors on;
}
# SPA 回退目标
location @spa {
proxy_pass https://$minio_host$bucket/index.html;
proxy_set_header Host $minio_host;
proxy_ssl_server_name on;
proxy_buffering on;
proxy_cache STATIC;
proxy_cache_key $scheme$proxy_host$uri$is_args$args;
add_header Cache-Control "no-cache, must-revalidate" always;
add_header X-Cache-Status $upstream_cache_status always;
}
}
}docker-compose.yml
docker-compose 配置非常简单。
docker-compose.yml
services:
nginx:
image: nginx:alpine
restart: unless-stopped
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx_cache:/var/cache/nginx
labels:
- "traefik.enable=true"
- "traefik.http.routers.app-mydomain.rule=Host(`app.mydomain.com`)"
- "traefik.http.routers.app-mydomain.entrypoints=websecure"
- "traefik.http.routers.app-mydomain.tls.certresolver=cloudflare"
- "traefik.http.routers.app-mydomain.tls.domains[0].main=mydomain.com"
- "traefik.http.routers.app-mydomain.tls.domains[0].sans=*.mydomain.com"If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow