Writing Skills
writing-skills
效率与协作技能,来自 obra/superpowers,查看原文获取完整用途和操作说明。
configure-reverse-proxy【部署与运维】Configure reverse proxy patterns across multiple tools including Nginx, Traefik, and ShinyProxy. Covers WebSocket proxying, path-based and host-based routing, SSL termination, and Docker label auto-discovery. Use when routing multiple services behind a single entry point, proxying WebSocket connections (Shiny, Socket.IO), auto-discovering Docker serv…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
以 Nginx、Traefik、或 ShinyProxy 設反向代理模式以路由流量至後端服務。
| Feature | Nginx | Traefik |
|---|---|---|
| Configuration | Static files | Docker labels / dynamic |
| Auto-discovery | No (manual) | Yes (Docker provider) |
| Let's Encrypt | Via certbot | Built-in ACME |
| Dashboard | No (3rd party) | Built-in |
| WebSocket | Manual config | Automatic |
| Best for | Static config, high traffic | Dynamic Docker environments |
server {
listen 80;
location /api/ {
proxy_pass http://api:8000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /app/ {
proxy_pass http://webapp:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
}
註: proxy_pass 尾 / 剝位置前綴。proxy_pass http://api:8000/; 配 location /api/ 將 /api/users 轉為 /users。
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://api:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://webapp:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
WebSocket 需升級頭。對 Shiny、Socket.IO、即時重載必需:
location /ws/ {
proxy_pass http://app:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
Shiny 應用特定:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
location / {
proxy_pass http://shiny:3838;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 86400;
proxy_buffering off;
}
}
預期: WebSocket 連接建且持。
失敗時: 查 proxy_http_version 1.1 已設。驗 Upgrade 與 Connection 頭。
docker-compose.yml:
services:
traefik:
image: traefik:v3.2
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
api:
image: myapi:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8000"
webapp:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.webapp.rule=Host(`app.example.com`)"
- "traefik.http.routers.webapp.entrypoints=websecure"
- "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
- "traefik.http.services.webapp.loadbalancer.server.port=3000"
volumes:
letsencrypt:
預期: Traefik 經標籤自動發現服務,行 SSL 憑證供給。
services:
api:
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`example.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.api.middlewares=strip-api"
- "traefik.http.middlewares.strip-api.stripprefix.prefixes=/api"
- "traefik.http.services.api.loadbalancer.server.port=8000"
labels:
- "traefik.http.middlewares.ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.ratelimit.ratelimit.burst=50"
- "traefik.http.middlewares.security.headers.stsSeconds=63072000"
- "traefik.http.middlewares.security.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security.headers.frameDeny=true"
- "traefik.http.routers.app.middlewares=ratelimit,security"
# Nginx: test config
docker compose exec nginx nginx -t
# Check routing
curl -H "Host: api.example.com" http://localhost/health
# Check WebSocket (needs wscat: npm install -g wscat)
wscat -c ws://localhost/ws/
# Traefik dashboard (if enabled)
# http://localhost:8080/dashboard/
預期: 請求路由至正確後端。WebSocket 升級成。
Host、X-Real-IP、X-Forwarded-For 頭docker compose restart 後仍存proxy_pass http://app/ vs http://app 於 Nginx 中路徑剝之行為不同proxy_read_timeout 為 60s。長駐 WebSocket 連接需 86400(24 時)/var/run/docker.sock 予其全 Docker 存取。用 ro 掛並慮 socket 代理resolver 127.0.0.11 以 Docker 內部 DNS 行動態服務proxy_buffering off:Shiny 與 SSE 端點需 proxy_buffering off 以行即時串流configure-nginx - 含 SSL 與安全頭之詳細 Nginx 配置deploy-shinyproxy - 容器化 Shiny 應用之 ShinyProxy 主機setup-compose-stack - 用反向代理之 compose 棧configure-api-gateway - 含 Kong 與 Traefik 之 API 閘道模式